在未评估的上下文中使用概念会产生不一致的结果
Using concepts in an unevaluated context gives inconsistent results
考虑以下无用的概念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')
上面的代码还合式吗?我应该信任哪个编译器?
概念名称并不像我们通常认为的那样基于表达式求值。概念名称解析为布尔值,表明 constraint-expression is satisfied or not:
A concept-id is a prvalue of type bool, and does not name a template specialization. A concept-id evaluates to true if the concept's normalized constraint-expression is satisfied ([temp.constr.constr]) by the specified template arguments and false otherwise
约束表达式被分解成原子片段。幸运的是,您的约束表达式只有一个原子部分:static_cast<T>(true)
。我们解析的方式whether an atomic constraint is satisfied is simple.有几个部分。第一部分是:
To determine if an atomic constraint is satisfied, the parameter mapping and template arguments are first substituted into its expression. If substitution results in an invalid type or expression, the constraint is not satisfied.
这就是编译器允许第一个的原因。 static_cast<S>(true)
不是有效的表达式,因为没有从 bool
到 S
的转换。所以不满足原子约束,所以C<S>
就是false
.
但是,static_cast<int>(true)
是 一个有效的表达式。所以我们继续第 2 部分:
Otherwise, the lvalue-to-rvalue conversion is performed if necessary, and E shall be a constant expression of type bool.
这就是我们 运行 进入单词“shall”的地方。在标准语言中,“应”的意思是“如果用户提供的代码不是 不是 的情况,则会出现编译错误”。 int
不是“bool
类型的常量表达式”。因此,代码不符合这个要求。并导致编译错误。
我想 GCC 只是将错误视为替换失败(或者它会自动将其强制转换为 bool
),但标准要求 MSVC/Clang 的错误输出行为。
考虑以下无用的概念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')
上面的代码还合式吗?我应该信任哪个编译器?
概念名称并不像我们通常认为的那样基于表达式求值。概念名称解析为布尔值,表明 constraint-expression is satisfied or not:
A concept-id is a prvalue of type bool, and does not name a template specialization. A concept-id evaluates to true if the concept's normalized constraint-expression is satisfied ([temp.constr.constr]) by the specified template arguments and false otherwise
约束表达式被分解成原子片段。幸运的是,您的约束表达式只有一个原子部分:static_cast<T>(true)
。我们解析的方式whether an atomic constraint is satisfied is simple.有几个部分。第一部分是:
To determine if an atomic constraint is satisfied, the parameter mapping and template arguments are first substituted into its expression. If substitution results in an invalid type or expression, the constraint is not satisfied.
这就是编译器允许第一个的原因。 static_cast<S>(true)
不是有效的表达式,因为没有从 bool
到 S
的转换。所以不满足原子约束,所以C<S>
就是false
.
但是,static_cast<int>(true)
是 一个有效的表达式。所以我们继续第 2 部分:
Otherwise, the lvalue-to-rvalue conversion is performed if necessary, and E shall be a constant expression of type bool.
这就是我们 运行 进入单词“shall”的地方。在标准语言中,“应”的意思是“如果用户提供的代码不是 不是 的情况,则会出现编译错误”。 int
不是“bool
类型的常量表达式”。因此,代码不符合这个要求。并导致编译错误。
我想 GCC 只是将错误视为替换失败(或者它会自动将其强制转换为 bool
),但标准要求 MSVC/Clang 的错误输出行为。