未评估的上下文(例如,requires-expressions)中的UB仍然是UB吗? [英] Is UB in unevaluated context (e.g. requires-expressions) still UB?
问题描述
C ++ 20 草稿 [concept.default.init]不能精确定义 default_initializable
The C++ 20 draft [concept.default.init] does not precisely define default_initializable
template<class T>
concept default_initializable = constructible_from<T> &&
requires { T{}; } &&
is-default-initializable <T>; // exposition-only
并用以下单词描述 is-default-initializable 应该做什么:
and describe what is-default-initializable should do with the following words:
对于类型
T
,是默认可初始化的< T>当且仅当变量定义为真时才为真
For a type
T
, is-default-initializable <T> is true if and only if the variable definition
T t;
的格式正确;否则,它是错误的.执行访问检查就像在与T无关的上下文.只有变量初始化的直接上下文的有效性是考虑过的.
is well-formed for some invented variable t; otherwise it is false. Access checking is performed as if in a context unrelated to T. Only the validity of the immediate context of the variable initialization is considered.
在 cppreference 上,我们发现了以下建议以实现可能的实施方式:>
On cppreference we find the following suggestion for a possible implementation:
template<class T>
concept default_initializable =
std::constructible_from<T> &&
requires { T{}; } &&
requires { ::new (static_cast<void*>(nullptr)) T; };
使用 nullptr
参数调用的placement-new运算符会导致未定义的行为.
The placement-new operator invoked with a nullptr
argument results in undefined behavior.
9)由标准单对象放置新表达式调用.标准库实现不执行任何操作,并返回未修改的ptr.如果通过放置新表达式调用此函数并且ptr是空指针,则该行为是不确定的.
9) Called by the standard single-object placement new expression. The standard library implementation performs no action and returns ptr unmodified. The behavior is undefined if this function is called through a placement new expression and ptr is a null pointer.
我的问题现在是:建议的可能实现实际上有效吗?一方面,我认为不可以,因为涉及到表现出未定义行为的表达式.另一方面,我认为是的,因为此表达式发生在未评估的上下文中,因此可能不需要具有明确定义的行为(?),而仅需要在语法上有效.但是我找不到一个明确的证据.
My question is now: is the suggested possible implementation actually valid? On the one hand I think no, because an expression is involved which exhibits undefined behavior. On the other hand I think yes, because this expression occurs in unevaluated context and therefore may not need to have well-defined behavior (?) and just needs to be syntactically valid. But I cannot find clear evidence for one or the other.
第二个问题:如果事实证明后者是正确的,那么为什么这种新放置的结构满足标准要求,即必须正确形成 T t;
?在我看来,这很奇怪,因为简单要求和复合要求都无法提供完全要求 T t;
的可能性.但是为什么这样做有效?
Second question: if the latter turns out to be true, then why does this placement-new construction satisfy the standard's requirement that T t;
must be well-formed? To me it looks like a strange hack, because neither simple nor compound requirements offer the possibility to require T t;
exactly. But why does this work?
推荐答案
When specified, undefined behavior are the consequence of an evaluation [expr.new]/20
如果分配函数是返回null的非分配形式([new.delete.placement]),则行为是不确定的.
If the allocation function is a non-allocating form ([new.delete.placement]) that returns null, the behavior is undefined.
出现在需求主体中的表达式是未评估的操作数.
Expressions appearing within a requirement-body are unevaluated operands.
未评估的操作数不被评估.
An unevaluated operand is not evaluated.
因此,没有未定义的行为,它需要放置新分配功能的返回值,但不会计算该值.
So there are no undefined behavior has it requires a return value of the placement new allocation function, but such value is not computed.
如果不是这种常见构造,则 decltype(std :: declval< int&>()+ std :: declval< int&>())
也是UB
If it were not the case such common construct decltype( std::declval<int&>() + std::declval <int&> ())
would be UB too.
这篇关于未评估的上下文(例如,requires-expressions)中的UB仍然是UB吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!