【问题标题】:Using concepts in an unevaluated context gives inconsistent results在未评估的上下文中使用概念会产生不一致的结果
【发布时间】:2021-08-24 15:37:29
【问题描述】:

考虑以下无用的概念C

template<class T>
concept C = static_cast<T>(true);

如果我们在未评估的上下文中将任意类型传递给C,那么all three compilers 将成功编译:

struct S {};
decltype(C<S>) x = 0;

但如果我们在未评估的上下文中将int 传递给C

decltype(C<int>) y = 0;

GCC 仍然接受它,while Clang and MSVC reject it with the same error message:

<source>:2:13: error: atomic constraint must be of type 'bool' (found 'int')

上面的代码仍然格式正确吗?我应该信任哪个编译器?

【问题讨论】:

  • 这当然很有创意。

标签: c++ language-lawyer c++20 c++-concepts


【解决方案1】:

概念名称并不像我们通常认为的那样基于对表达式求值。概念名称解析为一个布尔值,用于判断 constraint-expression is satisfied or not:

concept-id 是 bool 类型的纯右值,并且不命名模板特化。如果指定的模板参数满足概念的规范化约束表达式 ([temp.constr.constr]),则概念 ID 的计算结果为 true,否则为 false

约束表达式被分解成原子片段。幸运的是,您的约束表达式只有一个原子片段:static_cast&lt;T&gt;(true)。我们解决whether an atomic constraint is satisfied is simple.的方式有几个部分。第一部分是:

要确定是否满足原子约束,首先将参数映射和模板参数代入其表达式。如果替换导致无效的类型或表达式,则不满足约束。

这就是编译器允许第一个的原因。 static_cast&lt;S&gt;(true) 不是一个有效的表达式,因为没有从 boolS 的转换。因此,原子约束不满足,所以C&lt;S&gt;false

但是,static_cast&lt;int&gt;(true) 一个有效的表达式。所以我们继续第 2 部分:

否则,必要时进行左值到右值的转换,E 应为 bool 类型的常量表达式。

这就是我们遇到“shall”这个词的地方。在标准语言中,“shall”的意思是“如果用户提供的代码不是,那么就会出现编译错误”。 int 不是“bool 类型的常量表达式”。因此,代码不符合此要求。并产生编译错误。

我想 GCC 只是将错误视为替换失败(或者它会自动将其强制转换为 bool),但标准要求 MSVC/Clang 的错误输出行为。

【讨论】:

    猜你喜欢
    • 2019-04-15
    • 1970-01-01
    • 1970-01-01
    • 2017-08-18
    • 2013-01-23
    • 1970-01-01
    • 2019-04-15
    相关资源
    最近更新 更多