有人知道为什么下面的代码返回0吗?什么时候返回1?
#include <iostream> #include <type_traits> template<typename T> concept A = requires(T t){{t} -> std::same_as<bool>;}; int main() { std::cout << A<bool> << "\n"; }
我用gcc13.1在编译器资源管理器上运行它(编译器选项:-std=c++20)并且它确实返回0。
qxsslcnc1#
在您的例子中,复合要求{t} -> same_as<bool>意味着decltype((t))的类型必须满足same_as<bool>。由于decltype((t))中的t是圆括号,它将被视为普通的左值表达式,这使得它的类型为bool&而不是bool,因此不满足约束。可以将返回类型限制为same_as<bool&>,或者使用C++23 decay-copy(auto(x))删除表达式的 cvref 限定符
{t} -> same_as<bool>
decltype((t))
same_as<bool>
t
bool&
bool
same_as<bool&>
auto(x)
template<typename T> concept A = requires(T t) { { auto(t) } -> std::same_as<bool>; };
bakd9h0s2#
这确实是一个相当令人惊讶的结果。recently in a clang frontend bug report出现了一个类似的问题,这启发了我最近的C++ weekly quiz。该结果是[expr.prim.req.compound]p1.3.2中措辞的结果,其内容为(* 强调我的 *):应满足decltype((E))的类型约束的立即声明的约束([temp.param])。并在下面有以下示例:[示例1:给定概念C和D,
requires { { E1 } -> C; { E2 } -> D<A1, ⋯, An>; };
相当于
requires { E1; requires C<decltype((E1))>; E2; requires D<decltype((E2)), A1, ⋯, An>; };
(包括在η为零的情况下)。- 结束示例]注意示例中decltype中带括号的表达式,例如:decltype((E1))。decltype中带括号的表达式的结果是,结果类型是bool &,而不是您期望的bool。这是由于[dcl.type.decltype]p1.5中的措辞:否则,如果E是左值,则decltype(E)是T&,其中T是E的类型;这意味着如果表达式是一个 lvalue,那么类型为 T 的带括号的 id-expression 的结果将是 T&。另一方面,如果我们有:
decltype
decltype((E1))
bool &
template <typename T> concept B=requires(T t){{!t}->std::same_as<bool>;};
注意!t,它会给予我们一个 * 纯右值 *,那么由于[dcl.type.decltype]p1.6,结果将是bool:否则,decltype(E)是E的类型。
!t
2条答案
按热度按时间qxsslcnc1#
在您的例子中,复合要求
{t} -> same_as<bool>
意味着decltype((t))
的类型必须满足same_as<bool>
。由于
decltype((t))
中的t
是圆括号,它将被视为普通的左值表达式,这使得它的类型为bool&
而不是bool
,因此不满足约束。可以将返回类型限制为
same_as<bool&>
,或者使用C++23 decay-copy(auto(x)
)删除表达式的 cvref 限定符bakd9h0s2#
这确实是一个相当令人惊讶的结果。recently in a clang frontend bug report出现了一个类似的问题,这启发了我最近的C++ weekly quiz。
该结果是[expr.prim.req.compound]p1.3.2中措辞的结果,其内容为(* 强调我的 *):
应满足decltype((E))的类型约束的立即声明的约束([temp.param])。
并在下面有以下示例:
[示例1:给定概念C和D,
相当于
(包括在η为零的情况下)。- 结束示例]
注意示例中
decltype
中带括号的表达式,例如:decltype((E1))
。decltype
中带括号的表达式的结果是,结果类型是bool &
,而不是您期望的bool
。这是由于[dcl.type.decltype]p1.5中的措辞:否则,如果E是左值,则decltype(E)是T&,其中T是E的类型;
这意味着如果表达式是一个 lvalue,那么类型为 T 的带括号的 id-expression 的结果将是 T&。
另一方面,如果我们有:
注意
!t
,它会给予我们一个 * 纯右值 *,那么由于[dcl.type.decltype]p1.6,结果将是bool
:否则,decltype(E)是E的类型。