C++ 20的草案 [concept.default.init]没有精确定义default_initializable
template<class T>
concept default_initializable = constructible_from<T> &&
requires { T{}; } &&
is-default-initializable <T>; // exposition-only
针对类型T,当且仅当以下变量定义:
T t;
在某个虚构变量t上是符合格式要求的,is-default-initializable <T> 为真;否则为假。访问检查被执行,就像在与T无关的上下文中一样。只考虑变量初始化的直接上下文的有效性。
在cppreference 上,我们找到了一个可能的实现建议:
template<class T>
concept default_initializable =
std::constructible_from<T> &&
requires { T{}; } &&
requires { ::new (static_cast<void*>(nullptr)) T; };
使用空指针参数调用placement-new运算符会导致未定义的行为。
引用自9):单个对象标准placement new表达式调用此函数。标准库实现不执行任何操作并返回未修改的ptr。如果通过placement new表达式调用此函数且ptr是空指针,则其行为未定义。
我的问题是:建议的实现是否有效?一方面,我认为不是,因为涉及到表现出未定义行为的表达式。另一方面,我认为是,因为此表达式出现在未求值上下文中,因此可能不需要具有良好定义的行为(?),只需要在语法上有效即可。但我找不到明确的证据支持其中的任何一种情况。
第二个问题:如果后者被证明是真的,那么为什么这个placement-new构造满足标准对
T t;
必须是良好形式的要求?对我来说,它看起来像一个奇怪的hack,因为既简单要求也复合要求都没有提供要求T t;
的可能性。但是为什么这能行?
int &foo
,代码if(false){std::cout<<foo;}
不属于UB,因为目标从未被实际使用。换句话说,如果代码没有被执行,就没有“行为”--没有行为,就不可能出现未定义行为。 - cdhowie