首页 > 解决方案 > 在 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

标签: c++c++20

解决方案


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

如果确实如此,那么无论如何你都不会得到false,你会得到一个格式错误的程序。例如,您是否做过:

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

ThenWorksWithA<BadArg>将触发 which 的实例化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>


推荐阅读