在C ++ 17中,标准库中的空标记类型现在具有标记为explicit
的默认构造函数,并且也是= default
。例如,std::piecewise_construct_t
现在定义为
struct piecewise_construct_t { explicit piecewise_construct_t() = default; };
我的问题很简单,这是C ++ 14改变的原因是什么?明确默认的显式默认构造函数(!)对于空类是什么意思?
(为了避免被标记为欺骗:this question从2010年开始询问显式默认构造函数的用途,但那是在C ++ 11之前和很久以前的事情,所以事情可能已经发生了变化。{ {3}}更新,但答案似乎表明无论是否存在默认构造函数,都会执行聚合初始化,因此我很好奇最新标准中此更改的原因。)
答案 0 :(得分:16)
图书馆变更的理由是LWG 2510 "Tag types should not be DefaultConstructible
":
std::experimental::optional
由于某些原因,指定其nullopt
类型不是DefaultConstructible
。它的标签类型in_place_t
没有这样做,标准类型的标准也不适用。结果证明非常不幸,请考虑以下事项:#include <memory> #include <array> void f(std::array<int, 1>, int) {} // #1 void f(std::allocator_arg_t, int) {} // #2 int main() { f({}, 666); // #3 }
#3的电话不明确。更糟糕的是,如果超载#1被删除,则呼叫工作正常。标记类型的全部要点是它需要在调用中提及或者它需要是转发参数,因此能够构造类似的标记类型是没有意义的。
LWG问题与CWG 1518 "Explicit default constructors and copy-list-initialization"并行发展,具有有用的背景。