在C++20中使用typename需要/概念?
请考虑以下 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但我在 clang 中观察到1 1。谁是对的,为什么?
$ clang++ --version
clang version 10.0.0-4ubuntu1
$ clang++ test.cc -std=c++20
$ ./a.out
1
1
回答
这里的概念只是命名 type 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;
};
现在两种配方(原件,我的替代品)将产生false的WorksWithA<BadArg>。