c++ - `typename` 何时可以与明确引用类型的标识符一起使用?

标签 c++ syntax language-lawyer

通常,typename 用于消除标识符可能引用类型或可能引用其他内容的情况之间的歧义:

template<class T>
void foo(typename T::type value) {
   // ...
}

当标识符已经是类型时,什么时候可以使用typename

1.如果已经有这个名字的类可以使用吗?

class MyClass{};

void foo(typename MyClass value) {}

2.它可以与声明为类型的模板参数一起使用吗?

template<class T>
void foo(typename T value) {}

3.它可以与明确类型的内部类一起使用吗?

class A {
   public:
    class B {};
};

// Compiles; no typename necessary
void foo(A::B value) {} 
// This compiles too on gcc and msvc
void bar(typename A::B value) {}

编译器解释

案例 1:MSVC 认为这可以; gcc 和 clang 抛出错误

情况 2:MSVC 认为这可以; gcc 和 clang 抛出错误

情况 3: A::B 是明确的类型,但 gcc 和 clang 现在允许使用 typename

最佳答案

关键字typename 只被C++ 允许syntax介绍一个template type parameter , 或 before a qualified name ,即包含 :: 标记的内容。

所以你的 #1 和 #2 格式错误,因为 MyClassT 是不合格的名称,不包含任何 ::

在限定名称之前,typename 标记是:

C++17 [temp.res]/3,5,6:

When a qualified-id is intended to refer to a type that is not a member of the current instantiation and its nested-name-specifier refers to a dependent type, it shall be prefixed by the keyword typename, forming a typename-specifier. ...

A qualified name used as the name in a class-or-decltype (Clause [class.derived]) or an elaborated-type-specifier is implicitly assumed to name a type, without the use of the typename keyword. In a nested-name-specifier that immediately contains a nested-name-specifier that depends on a template parameter, the identifier or simple-template-id is implicitly assumed to name a type, without the use of the typename keyword. [Note: The typename keyword is not permitted by the syntax of these constructs. - end note]

If, for a given set of template arguments, a specialization of a template is instantiated that refers to a qualified-id that denotes a type or a class template, and the qualified-id refers to a member of an unknown specialization, the qualified-id shall either be prefixed by typename or shall be used in a context in which it implicitly names a type as described above.

所以你的 #3 是格式正确的,即使名称不依赖于模板参数,甚至不在模板声明中也是如此。

注意 C++20 将添加 many more contexts其中 typename 是可选的,即使是从属名称也是如此,因为可以从上下文中明确地确定该名称只能表示一种类型。

关于c++ - `typename` 何时可以与明确引用类型的标识符一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55777503/

相关文章:

c++ - 基数或 [[no_unique_address]] 成员的填充是否可用于存储其他基数/成员?

c++ - 段错误 : 11 while using boost mutex

c++ - 有没有一种正统的方法来避免编译器警告 C4309 - "truncation of constant value"与二进制文件输出?

java - Java 中 Class<?> 是什么意思?

c++ - 利用 `std::weak_ptr` 实现自杀对象

c - C 从指向结构体第二个成员的指针获取指向结构体的指针是否合法?

c++ - Qt 5 beta2, Qt Creator 2.6, MSVC error : Qt Creator needs a compiler set up to build. 在套件选项中配置编译器

c++ - 类方法和全局函数中的别名

mysql - 表名附近的错误 "You have an error in your SQL syntax;"

mysql - 字段列表中的列 `D1` 不明确