19

在 C++17 中,标准库中的空标记类型现在具有标记为 的默认构造函数explicit,并且也是= default. 例如,std::piecewise_construct_t现在定义为

struct piecewise_construct_t { explicit piecewise_construct_t() = default; };

我的问题很简单,从 C++14 发生这种变化的原因是什么?显式默认的显式默认构造函数(!)对于空类意味着什么?

(为了避免被标记为骗子:这个问题从 2010 年开始询问显式默认构造函数的目的,但那是 C++11 之前和很久以前的事了,所以事情可能已经改变了。这个问题是最近的,但是答案似乎表明,无论是否存在默认构造函数,都会执行聚合初始化,所以我很好奇最新标准中这种变化的原因。)

4

1 回答 1

16

库更改的基本原理在LWG 2510“标签类型不应该是DefaultConstructible

std::experimental::optional,由于某些原因,将其nullopt类型指定为 not 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”一起发展,具有有用的背景。

于 2017-05-25T00:03:41.540 回答