小编Kno*_*abe的帖子

为什么我必须用括号表示逗号表达式的初始化表达式?

煮一个问题我已经了解它的本质,我可以通过首先在逗号表达式中执行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都抱怨尝试yvoid表达式初始化.

为什么我必须将逗号表达式括起来以将其用作初始值设定项?

c++ initialization comma-operator

3
推荐指数
1
解决办法
139
查看次数

如何将产生的线程拖延足够长的时间来产生线程来做某事?

另一个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,并且需要处理虚假唤醒的可能性,据我所知,这对于互斥体来说不是问题. …

c++ multithreading c++11

2
推荐指数
1
解决办法
226
查看次数

在课外定义的默认移动操作的异常规范是什么?

考虑这个课程:

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的推理是否正确?

standards move exception-specification c++11

2
推荐指数
1
解决办法
149
查看次数

基于unique_ptr的pimpl类中的move构造函数是否需要完整的类型?

如果我使用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在最后一个语句中调用引起的内存泄漏并不重要.

c++ unique-ptr move-constructor c++11

2
推荐指数
1
解决办法
203
查看次数

为什么派生类中复制/移动函数的"正常"实现的行为会有所不同,具体取决于它们的定义方式?

当派生类复制和移动函数调用它们的基类版本时,我对我所看到的行为感到困惑.

我有一个基类与各种构造函数,告诉我什么时候被调用:

#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)

c++ constructor-overloading c++11 universal-reference

1
推荐指数
1
解决办法
124
查看次数

如何否定std :: is_integral用于标签调度?

我一直在玩标签调度,以下代码完全符合我的预期:

#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)

但这不会编译.

我需要做些什么才能使此代码生效?

c++ template-meta-programming c++11

1
推荐指数
2
解决办法
706
查看次数

如何将std :: endl传递给函数并使用它?

我想弄清楚如何将操纵器传递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才能编译代码?

c++ manipulators

1
推荐指数
1
解决办法
837
查看次数