如何定义带非尾置decltype返回类型的类模板外联成员函数
类模板成员函数外联实现的正确姿势
你遇到的问题其实是类模板作用域下的成员访问问题,咱们一个个拆解你试的写法为啥行不通:
- 第一种写法
template <class T> decltype(x) foo<T>::f1() {}:这里的x在类外部的全局作用域里根本找不到,编译器不知道它是foo<T>的成员,自然会报错。 - 第二种写法
template <class T> auto foo<T>::f1() -> decltype(x) {}:尾随返回类型里的x同样没限定所属的类模板,编译器认不出它是foo<T>的成员,所以也不行。 - 第三种写法
template <class T> auto foo<T>::f1() { return x; }:C++11里的auto推导返回类型依赖函数体里的return语句,而且模板实例化时遇到复杂场景容易出推导问题,不是稳妥的通用写法。 - 第四种写法方向是对的,但大概率是漏了包含
<utility>头文件(std::declval定义在这个头里),导致编译器找不到这个函数。
下面给你几个能正常工作的正确写法:
写法一:尾随返回类型 + this->x
在成员函数的尾随返回类型中,this指向当前foo<T>实例,通过它就能正确关联到成员x的类型:
template <class T> auto foo<T>::f1() -> decltype(this->x) { return x; // 这里的x在成员函数作用域内,编译器能识别是类的成员 }
写法二:直接用decltype(foo<T>::x)
既然x是foo<T>的成员,直接通过类模板限定符访问它的类型即可,不需要实例化对象:
template <class T> decltype(foo<T>::x) foo<T>::f1() { return x; }
写法三:完善你的第四种写法
只要补上<utility>头文件,std::declval就能帮你生成foo<T>的右值引用,从而获取x的类型:
#include <utility> template <class T> decltype(std::declval<foo<T>>().x) foo<T>::f1() { return x; }
这三种写法都能解决问题,选你觉得顺手的用就行~
内容的提问来源于stack exchange,提问作者Marc Aldorasi
相关产品推荐
相关产品推荐

