为什么在 C++20 中的这种情况下仍然需要 `typename` 前缀?

Why is `typename` prefix still required in such a case in C++20?

根据

One of the new features in C++20 is Down with typename.

In C++17, you had to provide the typename keyword in nearly all† dependent contexts to disambiguate a type from a value. But in C++20, this rule is relaxed a lot. In all contexts where you need to have a type, the typename keyword is no longer mandatory.

template<typename T>
concept IsOK = true;

template<typename T>
requires IsOK<T::U> // error: use ‘typename T::U’
void f()
{}

struct A
{
    using U = int;
};

int main()
{
    f<A>(); 
}

在上面的代码中,显然,IsOK 概念只能接受类型。

为什么这里需要typename

online demo

答案是笼统地谈论“上下文”的含义。 the feature 正在做的是找到 语法上不可能 除了类型名称之外的任何东西都出现在那个位置的地方。这是那些不再需要 typename 的地方。

例如,using name = X;。从语法上讲,这是一个类型别名声明。因此,无论 X 是什么,语法 都要求 它是一种类型。如果 X 恰好是一个依赖于模板参数的名称,那么无论该名称是什么,都必须是一个类型。所以语法没有歧义,typename是多余的。

语法 name<X> 声明 X 是模板 name 的模板参数。但是模板参数不必是类型。 specific 模板可以将类型作为特定参数,但 语法上X 可能是引用变量或模板的标识符.因此,您必须消除歧义依赖 Xs.