在 C++20 中使用类型名称需要/概念?

  • 本文关键字:概念 C++20 类型 c++ c++20
  • 更新时间 :
  • 英文 :


请考虑以下C++20程序:

#include <iostream>
template<typename T>
struct A {
using X = typename T::X;
};
template<typename T>
constexpr bool WorksWithA = requires { typename A<T>; };
struct GoodArg {
using X = int;
};
struct BadArg {
};
int main() {
std::cout << WorksWithA<GoodArg> << std::endl;
std::cout << WorksWithA<BadArg> << std::endl;
}

这是格式错误的吗? 如果不是,输出应该是什么?

我期待输出是1 0但我观察到叮当1 1. 谁是对的,为什么?

$ clang++ --version
clang version 10.0.0-4ubuntu1 
$ clang++ test.cc -std=c++20
$ ./a.out 
1
1

这里的概念只是命名类型A<BadArg>,它不做任何事情来触发它的实例化。这里没有任何内容会导致A<BadArg>::X格式不正确的实例化。

如果是这样,那么你无论如何都不会得到false,你会得到一个格式不正确的程序。例如,如果你做了:

template<typename T>
constexpr bool WorksWithA = requires { A<T>{}; };

然后WorksWithA<BadArg>会触发A<BadArg>的实例化,它会尝试查找BadArg::X,这在替换的直接上下文之外是一个失败。不false,编译错误。

如果你想要一个false的结果,你必须将A模板约束在现有的类型上:

template <typename T>
requires requires { typename T::X; }
struct A {
using X = typename T::X;
};

现在两种配方(你的原始和我的替代品)都会产生falseWorksWithA<BadArg>.

最新更新