C++17 中的显式默认构造函数

Explicit default constructors in C++17

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

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

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

(为了避免被标记为欺骗:this question from 2010 asks about the purpose of explicit default constructors, but that was pre-C++11 and a long time ago now so things have likely changed. 是最近的,但答案似乎表明无论是否存在默认构造函数,都会执行聚合初始化,所以我很好奇了解最新标准中此更改的原因。)

库更改的基本原理在 LWG 2510 "Tag types should not be DefaultConstructible":

std::experimental::optional, for certain reasons, specifies its nullopt type to not be DefaultConstructible. It doesn't do so for its tag type in_place_t and neither does the standard proper for any of its tag types. That turns out to be very unfortunate, consider the following:

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

The call at #3 is ambiguous. What's even worse is that if the overload #1 is removed, the call works just fine. The whole point of a tag type is that it either needs to mentioned in a call or it needs to be a forwarded argument, so being able to construct a tag type like that makes no sense.

LWG 问题与 CWG 1518 "Explicit default constructors and copy-list-initialization" 并行发展,后者具有有用的背景。