c++ 关于概念和要求的使用问题

klr1opcd  于 2023-05-20  发布在  其他
关注(0)|答案(2)|浏览(97)

有人知道为什么下面的代码返回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。

qxsslcnc

qxsslcnc1#

在您的例子中,复合要求{t} -> same_as<bool>意味着decltype((t))的类型必须满足same_as<bool>
由于decltype((t))中的t是圆括号,它将被视为普通的左值表达式,这使得它的类型为bool&而不是bool,因此不满足约束。
可以将返回类型限制为same_as<bool&>,或者使用C++23 decay-copyauto(x))删除表达式的 cvref 限定符

template<typename T>
concept A = requires(T t) {
  { auto(t) } -> std::same_as<bool>;
};
bakd9h0s

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&
另一方面,如果我们有:

template <typename T>
concept B=requires(T t){{!t}->std::same_as<bool>;};

注意!t,它会给予我们一个 * 纯右值 *,那么由于[dcl.type.decltype]p1.6,结果将是bool
否则,decltype(E)是E的类型。

相关问题