使用模板数组别名声明返回void的友元函数模板编译报错解决
模板数组别名与友元函数模板的编译错误解决
我查了很多相关帖子,但没找到适配自己使用场景的解决方案。我想为同一模板类的两个实例组成的数组创建类型别名,并用这个别名声明返回值为void的函数模板,同时让该函数模板成为模板类A的友元。但代码编译失败,报错行是template<typename T> void doSomething(array2As);,错误信息是error: variable or field 'doSomething' declared void。我推测编译器无法将array2As的类型定义与模板参数T关联,请问该怎么解决?
原classA.h代码
//classA.h file #include <type_traits> #include <iostream> using std::is_same; using std::cout; using std::endl; template<typename T> class A; template<typename T> using array2As = A<T>[2]; template<typename T> void doSomething(array2As); template<typename T> class A{ public: A(T); private: friend void doSomething(array2As); A()=delete; A(const A&)=delete; A& operator=(const A&)=delete; T elem; }; template<typename T> A<T>::A(T elem){ static_assert(is_same<T,int>::value || is_same<T,double>::value, "Compilation error: type must be int or double"); this.elem = elem; } template<typename T> void doSomething(array2As a){ if(is_same<T,int>::value){ auto sz = sizeof(a)/sizeof(int);} else{auto sz = sizeof(a)/sizeof(double);} static_assert(2 == sz, "Compilation error: array must have exactly 2 elements"); for(auto i=0; i<sizeof(a);++i){ auto T& = a[i]; cout << T.elem << endl; } return; }
报错信息
报错行:
template<typename T> void doSomething(array2As);错误信息:
error: variable or field 'doSomething' declared void
原main.cpp代码
#include "classA.h" int main (){ array2As a = {A(5),A(7)}; doSomething(a); array2As b = {A(1.2),A(6.3)}; doSomething(b); return 0; }
问题根源
核心问题是:array2As是带模板参数的类型别名,直接写array2As相当于未提供模板实参,编译器无法将其与函数模板的T关联,会把它当成未定义标识符,导致函数声明语法错误。此外代码还有几处语法细节错误,一并影响编译。
修复方案
1. 修正函数模板的声明与定义
明确给array2As指定模板参数T,写成array2As<T>,让编译器能关联别名和模板参数。
2. 修正友元声明
友元声明同样需要指定array2As<T>,并通过doSomething<>明确这是已声明的函数模板特化,避免编译器将其视为新的非模板函数。
3. 修复其他语法错误
- 构造函数中
this.elem改为this->elem(指针访问成员需用->) doSomething中auto T& = a[i];是语法错误,改为T& elem_ref = a[i];- 循环条件
i < sizeof(a)错误,sizeof(a)是数组总字节数,改用计算出的数组长度sz - 数组长度计算改用通用方式
sizeof(a)/sizeof(a[0]),无需分支判断
修复后的完整代码
classA.h
#include <type_traits> #include <iostream> using std::is_same; using std::cout; using std::endl; template<typename T> class A; template<typename T> using array2As = A<T>[2]; // 明确指定array2As的模板参数T template<typename T> void doSomething(array2As<T>); template<typename T> class A{ public: A(T); private: // 友元声明绑定当前类的模板参数T friend void doSomething<>(array2As<T>); A()=delete; A(const A&)=delete; A& operator=(const A&)=delete; T elem; }; template<typename T> A<T>::A(T elem){ static_assert(is_same<T,int>::value || is_same<T,double>::value, "Compilation error: type must be int or double"); this->elem = elem; // 修正指针成员访问方式 } template<typename T> void doSomething(array2As<T> a){ auto sz = sizeof(a)/sizeof(a[0]); // 通用数组长度计算 static_assert(2 == sz, "Compilation error: array must have exactly 2 elements"); for(auto i=0; i<sz; ++i){ T& elem_ref = a[i]; // 修正引用声明语法 cout << elem_ref.elem << endl; // 访问私有成员elem } return; }
main.cpp
#include "classA.h" int main (){ // 明确指定array2As的模板参数 array2As<int> a = {A<int>(5), A<int>(7)}; doSomething(a); array2As<double> b = {A<double>(1.2), A<double>(6.3)}; doSomething(b); return 0; }
内容的提问来源于stack exchange,提问作者Vinod
相关产品推荐
相关产品推荐

