typename的两种用法

typename有两种用法,第一种用于声明模板时,表示模板类型参数,如下所示。在用于模板声明时,typename 和 class 等价,具有同等含义。

template<typename T> class MyClass;
// 等价于
template<class T> class MyClass;

typename的第二种用法,用于表示一个类内所指的类型为一个 “class” 类型(内置类型、自定类型),而非其他(变量、函数类型)。更一般的说法是,typename 用来告诉编译器类中的嵌套名称表示的是一个类型。看下面一个例子。

class MyCls {
   
public:
    using value = int;
};

template<typename T>
void func(T t)
{
   
    typename T::value v = 10;
    std::cout << v << std::endl;
}

void test_MyCls()
{
   
    MyCls m;
    func(m);
}

int main()
{
   
    test_MyCls();
}

我的编译环境为: Ubuntu 20.04 + g++ (GCC) 11.3.0。编译上述代码,能正确编译通过。
在这里插入图片描述
若将 func 中的 typename 关键字去掉,则会编译失败,编译结果如下所示:
在这里插入图片描述

编译报错的主要原因是,在模板实例化的过程中,T::value 没有被解析为一个类型,如编译结果中红色圈出的部分所示。但可能会存在这样一种疑问,在上面的示例中,模板参数T在模板实例化的过程中解析为 MyCls,而 MyCls::value 在 MyCls 中被声明为 int 的别名,因此 T::value 被实例化为 MyCls::value 后表示的应该就是一个类型。这样直觉的理解看似没问题,但违反了C++中的模板解析规则。在模板实例化之前,会先对语法进行解析,当解析到 T::value 时,T还没被实例化为一个具体的类型,因此 T::value 可能表示的是一个类型,也可能表示的是一个 static 变量,也可能是一个全局的变量,因此 T::value 就存在了歧义,因此编译器编译不通过。为了解决这种起义,C++中规定,当使用类中的嵌套类型时,需要使用 typename 进行声明。


在 《Effective C++》的条款42中,对类中的嵌套类型的描述摘录如下。

template 内出现的名称如果相依于某个template参数,称之为从属名称(dependent names)。如果从属名称在 class 内呈嵌套状,我们称它为从属嵌套名称(nested dependent name)。

因此有了规则 “typename 必须作为嵌套从属类型名称的前缀词”。

“typename 必须作为嵌套从属类型名称的前缀词” 这一规则的例外是,typename 不可以出现在 base classes list 内的嵌套从属名称之前,也不可以在 member initialization list 中作为 base class 修饰符。

在这里插入图片描述

相关推荐

  1. using和typename在C++中

    2023-12-13 17:08:02       11 阅读
  2. Rust 中Self 关键字不同

    2023-12-13 17:08:02       19 阅读
  3. pd.groupby2

    2023-12-13 17:08:02       37 阅读
  4. C# 四定时器

    2023-12-13 17:08:02       15 阅读
  5. Servlet

    2023-12-13 17:08:02       9 阅读
  6. Flutter路由

    2023-12-13 17:08:02       43 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-13 17:08:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-13 17:08:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-13 17:08:02       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-13 17:08:02       20 阅读

热门阅读

  1. Modbus RTU和Modbus TCP的区别 深入篇

    2023-12-13 17:08:02       36 阅读
  2. vue3中Element Plus全局组件配置中文的两种方案

    2023-12-13 17:08:02       40 阅读
  3. Temporal 服务限制说明

    2023-12-13 17:08:02       44 阅读
  4. Spring框架中的8种设计模式

    2023-12-13 17:08:02       37 阅读
  5. 每日一练 | 华为认证真题练习Day29

    2023-12-13 17:08:02       41 阅读
  6. 选择排序

    2023-12-13 17:08:02       40 阅读
  7. 【Android】通知(未完待续)

    2023-12-13 17:08:02       43 阅读
  8. PHP中什么是命名空间(Namespace)?

    2023-12-13 17:08:02       43 阅读