在嵌套名称说明符中使用 simple-template-id 是否明确表示类模板特化?

jac*_*k X 8 c++ templates language-lawyer name-lookup

struct A{
    template<typename U>
    void T(){}
};
struct B{
    template<typename U>
    struct T{
       using type = U;
    };
};
struct C:A,B{

};
int main(){
    C::T<int>::type d;
}
Run Code Online (Sandbox Code Playgroud)

这个例子不被 GCC 和 Clang 接受。

根据basic.lookup.qual#1

可以在?::? 之后引用类或命名空间成员或枚举器的名称。作用域解析运算符 ([expr.prim.id.qual]) 应用于表示其类、命名空间或枚举的嵌套名称说明符。如果一个?::?嵌套名称说明符中的范围解析运算符前面没有 decltype-说明符,查找 ?::? 之前的名称。仅考虑专门化为 types 的命名空间、类型和模板

这意味着在查找模板 name 的声明时T, 的特化T应表示此上下文中的类型。另一方面,根据class.member.lookup#4

如果 C 包含名称 f 的声明,则声明集包含在 C 中声明的满足发生查找的语言构造要求的每个 f 声明。

同样,T在 范围内查找模板时C,该查找只应考虑那些特化为类型的模板。的范围C没有任何声明T,因此将S(T,C)在其每个基类中执行查找。模板TA不符合要求。同时,T在范围内声明的模板B确实满足要求。所以查找没有歧义,B::T是唯一的结果。这意味着C::T<int>::type d应该是格式良好的。为什么 GCC 和 Clang 都拒绝这个例子?它可以被认为是两者的错误吗?如果我错过了什么,这个例子应该格式错误的原因是什么?

Dav*_*ing 4

查找依赖所需的前瞻甚至被认为是不可取的,因为依赖项的解释取决于的含义。因此,对后面跟着的名称的查找不限于类型和命名空间,无论稍后找到什么。 P1787R6修复了这个问题,将特殊查找限制为紧随其后的标识符因为其他类型的名称无论如何都可以引用类型或命名空间)。T::<T<>::::

\n