煮一个问题我已经了解它的本质,我可以通过首先在逗号表达式中执行do-nothing lambda来将变量初始化为int,如下所示:
int main(){
auto x = ( []{}(), 10 ); // same effect as auto x = 10;
}
Run Code Online (Sandbox Code Playgroud)
但如果我没有将初始化表达式括起来,
int main(){
auto y = []{}(), 10; // won't compile
}
Run Code Online (Sandbox Code Playgroud)
所有gcc,clang和MSVC都抱怨尝试y用void表达式初始化.
为什么我必须将逗号表达式括起来以将其用作初始值设定项?
另一个SO线程解释了如何使用thread::native_handleC++线程API之外的东西(例如,设置线程的优先级).要点是:
std::thread t(functionToRun);
auto nh = t.native_handle());
// configure t using nh
Run Code Online (Sandbox Code Playgroud)
这种方法的问题在于,functionToRun在配置t的代码完成之前,可以执行任意时间量(包括完成).
我相信我们可以防止这种情况发生如下(未经测试):
std::atomic<bool> configured(false);
std::thread t([&]{ while (!configured); // spin until configured is true
functionToRun(); });
auto nh = t.native_handle();
// configure t using nh
configured = true;
Run Code Online (Sandbox Code Playgroud)
不幸的是,这导致生成的线程旋转等待configured变为真.产生的线程最好在配置完成之前阻塞.
实现这一目标的一种方法似乎是使用互斥锁(也是未经测试的):
std::mutex m;
std::unique_lock<std::mutex> lock(m);
std::thread t([&]{ std::lock_guard<std::mutex> lg(m); // block until m available
functionToRun(); });
auto nh = t.native_handle();
// configure t using nh
lock.unlock(); // allow t to continue
Run Code Online (Sandbox Code Playgroud)
这似乎应该可以工作,但是,从概念上讲,似乎condvar更适合于指示何时满足条件(配置完成)的工作.但是使用condvar需要上述所有内容,加上condvar,并且需要处理虚假唤醒的可能性,据我所知,这对于互斥体来说不是问题. …
考虑这个课程:
class C1 {
C1(C1&&) = default; // declare and define move ctor
};
Run Code Online (Sandbox Code Playgroud)
因为C1的移动ctor在其第一个声明中被明确默认,所以标准的8.4.2告诉我们它具有相同的异常规范(ES),就好像该函数已被隐式声明一样.然后我们可以使用15.4/14和12.8/15来得出其ES的结论noexcept(true).
现在考虑一个C2相同的类,除了它的移动ctor在类定义之外默认:
class C2 {
C2(C2&&); // declare move ctor
};
C2::C2(C2&&) = default; // define move ctor
Run Code Online (Sandbox Code Playgroud)
C2移动ctor的ES是多少?因为它的第一次声明没有违约,所以8.4.2/2不适用.因为它没有明确的ES,所以8.4.2/3不适用.因为没有隐含声明,15.4/14不适用.据我所知,这意味着15.4/12适用,它表示默认函数ES是noexcept(false).
如果我是对的,这意味着C1中的移动ctor是noexcept(true),但C2中的概念相同的移动ctor是noexcept(false).
我对C2的推理是否正确?
如果我使用a unique_ptr<T>来构建一个pimpl类,我理解调用T析构函数的编译器生成的函数需要T是一个完整的类型.但是pimpl类的移动构造函数呢?编译器生成的版本只调用了unique_ptr移动构造函数.该功能不会破坏任何东西.此外,pimpl类生成的移动构造函数是隐式的noexcept,因此它的主体不可能抛出异常,导致它必须退出并销毁unique_ptr子对象.
看起来好像下面的代码应该编译:
#include <memory>
class Widget { // has implicit move ctor
struct Impl;
std::unique_ptr<Impl> pImpl;
};
int main()
{
Widget *pw1 = nullptr;
new Widget(std::move(*pw1)); // call move ctor. Rejected by
} // gcc, clang, and MSVC
Run Code Online (Sandbox Code Playgroud)
正如评论所说,这个代码被所有gcc,clang和MSVC拒绝.每个人抱怨对不完整类型的操作无效.这是标准要求的吗?如果是这样,那是哪一部分
请注意,此处的问题是编译,因此上述代码由于取消引用空pw1指针而未定义的运行时行为无关紧要.出于同样的原因,new在最后一个语句中调用引起的内存泄漏并不重要.
当派生类复制和移动函数调用它们的基类版本时,我对我所看到的行为感到困惑.
我有一个基类与各种构造函数,告诉我什么时候被调用:
#include <iostream>
class Base {
public:
Base() {}
template<typename T>
Base(T&&) { std::cout << "URef ctor\n"; }
Base(const Base&) { std::cout << "Copy ctor\n"; }
Base(Base& rhs): Base(const_cast<const Base&>(rhs))
{ std::cout << " (from non-const copy ctor)\n"; }
Base(Base&&) { std::cout << "Move ctor\n"; }
Base(const Base&& rhs): Base(rhs)
{ std::cout << " (from const move ctor)\n"; }
};
Run Code Online (Sandbox Code Playgroud)
对于具有编译器生成的复制和移动操作的派生类
class Derived: public Base {};
Run Code Online (Sandbox Code Playgroud)
和这个测试代码,
int main()
{
Derived d;
Derived copyNCLValue(d);
Derived copyNCRvalue(std::move(d));
const Derived cd; …Run Code Online (Sandbox Code Playgroud) 我一直在玩标签调度,以下代码完全符合我的预期:
#include <type_traits>
#include <iostream>
void impl(std::true_type) { std::cout << "true\n"; }
void impl(std::false_type) { std::cout << "false\n"; }
template<typename T>
void dispatch(T&& val)
{
impl(std::is_integral<typename std::remove_reference<T>::type>());
}
int main()
{
dispatch(10); // calls impl(std::true_type)
dispatch(""); // calls impl(std::false_type)
}
Run Code Online (Sandbox Code Playgroud)
但如果我想否定这个条件,我就会遇到麻烦.我想我可能只是抛出一个" !"到里面的代码dispatch,
impl(!std::is_integral<T>()); // added "!"
Run Code Online (Sandbox Code Playgroud)
但这不会编译.
我需要做些什么才能使此代码生效?
我想弄清楚如何将操纵器传递std::endl给函数,然后在函数中使用传入的操纵器.我可以声明这样的函数:
void f(std::ostream&(*pManip)(std::ostream&));
Run Code Online (Sandbox Code Playgroud)
我可以这样称呼它:
f(std::endl);
Run Code Online (Sandbox Code Playgroud)
那一切都很好.我的问题是弄清楚如何在里面使用操纵器f.这不起作用:
void f(std::ostream&(*pManip)(std::ostream&))
{
std::cout << (*pManip)(std::cout); // error
}
Run Code Online (Sandbox Code Playgroud)
无论编译器如何,错误消息都归结为编译器无法确定operator<<要调用的内容.我需要修复哪些内容f才能编译代码?