C++模板类中成员函数的名称解析
C++ name resolution for member functions in template class
#include <iostream>
template<class T> struct A {
typedef T a;
};
template<class T>
struct B {
typedef typename A<T>::a a;
static a foo(a b);
};
template<class T>
a B<T>::foo(a b) {return b}
int main() {
std::cout << B<int>::foo(1);
}
给出以下错误:(尝试一下)。
main.cpp:13:1: error: 'a' does not name a type
a B<T>::foo(a b) {return b}
内联定义不会受到此错误的影响。
有人可以解释为什么编译器在这种情况下无法解决a
,以及我如何使这段代码工作。
我不想明确解决所有名称,例如
typename B<T>::a B<T>::foo(typename B<T>::a b) {return b}
因为它会降低可读性。
这是因为这里的a
仍在全局范围内查找:
template<class T>
a B<T>::foo(a b) {return b;}
^^
您正在对a
进行不合格的查找。到达定义的B<T>::
部分后,该范围将添加到所有进一步的查找中。因此,b
参数的类型将在B<T>
范围内查找。
您只需将其限定为返回类型:
template<class T>
typename B<T>::a B<T>::foo(a b) {return b;}
相关规则是为什么可以在 [basic.lookup.unqual]/8 中找到参数类型a
:
对于类 X 的成员,成员函数体、默认参数、异常规范中使用的名称, 在非静态数据成员 (9.2) 的大括号或等于初始值设定项中,或在类的定义中 在 X 定义之外的成员,在成员的声明者 ID 之后,应在 以下方式:
— 在使用它的块或封闭块中使用之前 (6.3),或
— 应是 X 类的成员或 X 类基本类的成员 (10.2),或
返回类型 a
与粗体文本(或上面的任何文本)不匹配,但参数类型 a
匹配。
如果C++11和14,则可以声明函数auto
以摆脱长返回类型。您需要在 C++11 中将其指定为尾随类型,但这允许您省略typename B<T>::
,因为编译器已经知道要查找的位置。
//C++11
template<class T>
auto B<T>::foo(a b) -> a {return b;}
//C++14
template<class T>
auto B<T>::foo(a b) {return b;}
相关文章:
- 如何使用指针传递给函数的数组中对象的函数成员
- c++构造函数成员初始化:传递参数
- 创建 std::函数,它返回具有函数成员值的变量.分段错误
- 如何在C++通过公共函数访问私有函数成员?
- 解释了构造函数成员初始化列表
- 调用std::函数成员时内存损坏
- 是否可以为模板类的模板函数成员设置别名?
- 捕获 lambda 函数C++成员变量
- 构造函数成员初始值设定项跨成员列出,安全吗?
- 获取与在模板参数中传递的函数成员类型相同的类
- 如何从公共函数成员访问地图私有成员
- C 构造函数成员分配优化
- 使用命名空间进行函数成员定义
- 函数成员作为 CUDA 内核的参数
- 模板基类函数成员的别名
- 函数成员中用于void和继承的enable_if
- 头文件中是否定义了一个很长的Class函数成员
- 类内/构造函数成员初始化
- 使用指向部分专用函数成员的指针自动填充向量
- 指向函数成员的指针