C++模板类成员函数外部实现时typename修饰返回类型语法疑问
问题原因解析
1. 为什么不能直接用reference作为返回值
类内部声明成员函数时,整个声明都处于类的作用域内,你提前定义的reference typedef 可以直接被识别。但类外实现模板类成员时:
- 函数返回值的位置处于类作用域之外,编译器无法识别未加限定的
reference属于哪个类的成员 - 只有函数名之后的参数列表、函数体部分,才会进入
vector<T, Allocator>的作用域,这部分的reference可以直接使用
2. 为什么必须加typename关键字
vector<T, Allocator>是依赖模板参数的「依赖类型」,编译器在解析模板的第一阶段,无法判断vector<T, Allocator>::reference到底是一个静态成员变量,还是一个嵌套定义的类型,所以必须手动加typename关键字,告知编译器这是一个类型,否则会报语法错误。
简化写法方案
下面是几种常用的简化方式,可根据你支持的C++标准选择:
- C++11及以上:后置返回类型(最常用)
后置返回类型位于函数名之后,已经进入类作用域,不需要加全限定名和typename:
template <typename T, typename Allocator> auto vector<T, Allocator>::operator[](size_type n) -> reference
- C++20及以上:auto自动推导返回值
如果函数实现的返回值类型明确,可以直接用auto推导,连后置返回类型都可以省略:
template <typename T, typename Allocator> auto vector<T, Allocator>::operator[](size_type n)
注意如果存在const/非const重载的场景,需要确保推导结果符合预期,运算符重载这类逻辑简单的场景基本不会出问题。
- 通用方案:提前定义类型别名
如果需要实现大量同返回类型的成员函数,可以在实现文件开头提前定义别名,减少重复代码:
template <typename T, typename Allocator> using VecReference = typename vector<T, Allocator>::reference;
后续实现成员函数时,返回值直接写VecReference<T, Allocator>即可。
补充说明:函数参数列表、函数体内使用
reference类型不需要加任何前缀,因为这部分已经处于类作用域内,可以直接识别。
内容的提问来源于stack exchange,提问作者Ajvar
相关产品推荐
相关产品推荐

