未评估的上下文(例如,requires-expressions)中的UB仍然是UB吗? [英] Is UB in unevaluated context (e.g. requires-expressions) still UB?

查看:65
本文介绍了未评估的上下文(例如,requires-expressions)中的UB仍然是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.

[expr.prim.req]/2 :

出现在需求主体中的表达式是未评估的操作数.

Expressions appearing within a requirement-body are unevaluated operands.

[expr.prop]/1 :

未评估的操作数不被评估.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆