首页 > 解决方案 > “需要”忽略一个字段不是静态的

问题描述

考虑以下代码:

#include <iostream>

constexpr int fun(int const&) { return 5; }
struct T { int x; };

int main() {
  std::cout << fun(T::x) << std::endl;                   // Line A
  std::cout << requires { fun(T::x); } << std::endl;     // Line B
}

如果我只注释 B 行,则无法编译代码(正如预期的那样,因为x在 中不是静态的T)。但是,当我只评论 A 行时,代码在 Clang 11.0.0 和 GCC 10.2.0 (都是 output 1)下编译得很好。我错过了requires什么?它不应该返回false吗?

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

解决方案


一个 requires 表达式是一大堆未计算的操作数。

[expr.prim.req]

2 requires-expression 是 bool 类型的纯右值,其值如下所述。出现在需求主体中的表达式是未计算的操作数。

命名非静态数据成员的限定 ID 总是可以出现在未计算的操作数中。

[expr.prim.id]

2只能使用表示类的非静态数据成员或非静态成员函数的 id 表达式:

  • 作为类成员访问的一部分,其中对象表达式引用成员的类或从该类派生的类,或

  • 形成指向成员 ([expr.unary.op]) 的指针,或

  • 如果该 id 表达式表示一个非静态数据成员并且它出现在未计算的操作数中。[ 例子:

struct S {
  int m;
};
int i = sizeof(S::m);           // OK
int j = sizeof(S::m + 42);      // OK

—结束示例]

可能出现的未计算操作数T::x可以是任何表达式。因此,即使是 C++20 之前的版本,您也可以例如编写

decltype(fun(T::x)) i{};

推荐阅读