Friend 模板重载运算符 <<: 未解析的外部符号
Friend template overloaded operator <<: unresolved external symbol
我遇到错误问题
Error LNK2019 unresolved external symbol "class std::basic_ostream > & __cdecl cop4530::operator<<(class std::basic_ostream > &,class rob::Stack const &)" (??6rob@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV12@ABV?$Stack@H@0@@Z) referenced in function _main Project7 c:\Users\Robrik\documents\visual studio 2015\Projects\Project7\Project7\post.obj 1
现在,post
正在做的就是调用 operator<<
宣言
namespace rob {
template < typename T> class Stack {
friend std::ostream& operator<< (std::ostream& os, const Stack<T>& a);
void print(std::ostream& os, char ofc = ' ') const;
private:
std::vector<T> arr;
};
定义
template < typename T>
inline std::ostream & rob::operator<<(std::ostream & os, const Stack<T>& a) {
return a.print(os, ' ');
}
template<typename T>
inline void rob::Stack<T>::print(std::ostream & os, char c) const
{
for (int i = 0; i != arr.size(); i++)
{
os << c << arr[i];
}
os << '\n';
}
它们分别位于.h
文件和.hpp
中,我要求运算符不是成员函数(用于赋值)。
您还应该在其实际所属的 rob 命名空间中声明函数签名:
namespace rob {
template <typename T>
class Stack {
friend std::ostream& operator<< (std::ostream& os, const Stack<T>& a);
};
template < typename T>
std::ostream& operator<< (std::ostream& os, const Stack<T>& a){
...
}
除了@LibertyPaul 的回答之外,您还需要添加一个 template<T>
to friend std::os...
行,才能工作:
namespace rob {
template <typename T> class Stack {
friend std::ostream& operator<< (std::ostream& os, const Stack<T>& a) {
return a.arr.print(os, ' ');
}
};
}
代码示例的问题;
template <typename T>
class Stack {
friend std::ostream& operator<< (std::ostream& os, const Stack<T>& a);
void print(std::ostream& os, char ofc = ' ') const;
// ...
};
是否将operator<<
声明为非模板函数。对于与 Stack
一起使用的每个类型 T
,都需要有一个非模板 operator<<
。例如声明了类型Stack<int>
,那么一定有如下的运算符实现;
std::ostream& operator<< (std::ostream& os, const Stack<int>& a) {/*...*/}
由于未实现,链接器无法找到它并导致出现错误。
作为旁注; gcc 警告如下
warning: friend declaration 'std::ostream& operator<<(...)' declares a non-template function [-Wnon-template-friend]
note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
这可能不是预期的,每个实例都有自己的实现。
要更正此问题,您可以在 Stack
类型之前声明一个模板运算符,然后声明为友元,即实例化。语法看起来有点别扭,但是看起来是这样的;
// forward declare the Stack
template <typename>
class Stack;
// forward declare the operator <<
template <typename T>
std::ostream& operator<<(std::ostream&, const Stack<T>&);
template <typename T>
class Stack {
friend std::ostream& operator<< <>(std::ostream& os, const Stack<T>& a);
// note the required <> ^^^^
void print(std::ostream& os, char ofc = ' ') const;
// ...
};
template <typename T>
std::ostream& operator<<(std::ostream&, const Stack<T>&)
{
// ... implement the operator
}
上面的代码将operator的friendship限定在Stack
对应的实例化中,即operator<< <int>
实例化仅限于访问Stack<int>
实例化的私有成员。
备选方案包括允许友谊扩展到模板的所有实例化;
template <typename T>
class Stack {
template <typename T1>
friend std::ostream& operator<<(std::ostream& os, const Stack<T1>& a);
// ...
};
operator<<
的实现可以在 class 定义内或外部内联完成。
我遇到错误问题
Error LNK2019 unresolved external symbol "class std::basic_ostream > & __cdecl cop4530::operator<<(class std::basic_ostream > &,class rob::Stack const &)" (??6rob@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV12@ABV?$Stack@H@0@@Z) referenced in function _main Project7 c:\Users\Robrik\documents\visual studio 2015\Projects\Project7\Project7\post.obj 1
现在,post
正在做的就是调用 operator<<
宣言
namespace rob {
template < typename T> class Stack {
friend std::ostream& operator<< (std::ostream& os, const Stack<T>& a);
void print(std::ostream& os, char ofc = ' ') const;
private:
std::vector<T> arr;
};
定义
template < typename T>
inline std::ostream & rob::operator<<(std::ostream & os, const Stack<T>& a) {
return a.print(os, ' ');
}
template<typename T>
inline void rob::Stack<T>::print(std::ostream & os, char c) const
{
for (int i = 0; i != arr.size(); i++)
{
os << c << arr[i];
}
os << '\n';
}
它们分别位于.h
文件和.hpp
中,我要求运算符不是成员函数(用于赋值)。
您还应该在其实际所属的 rob 命名空间中声明函数签名:
namespace rob {
template <typename T>
class Stack {
friend std::ostream& operator<< (std::ostream& os, const Stack<T>& a);
};
template < typename T>
std::ostream& operator<< (std::ostream& os, const Stack<T>& a){
...
}
除了@LibertyPaul 的回答之外,您还需要添加一个 template<T>
to friend std::os...
行,才能工作:
namespace rob {
template <typename T> class Stack {
friend std::ostream& operator<< (std::ostream& os, const Stack<T>& a) {
return a.arr.print(os, ' ');
}
};
}
代码示例的问题;
template <typename T>
class Stack {
friend std::ostream& operator<< (std::ostream& os, const Stack<T>& a);
void print(std::ostream& os, char ofc = ' ') const;
// ...
};
是否将operator<<
声明为非模板函数。对于与 Stack
一起使用的每个类型 T
,都需要有一个非模板 operator<<
。例如声明了类型Stack<int>
,那么一定有如下的运算符实现;
std::ostream& operator<< (std::ostream& os, const Stack<int>& a) {/*...*/}
由于未实现,链接器无法找到它并导致出现错误。
作为旁注; gcc 警告如下
warning: friend declaration 'std::ostream& operator<<(...)' declares a non-template function [-Wnon-template-friend]
note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
这可能不是预期的,每个实例都有自己的实现。
要更正此问题,您可以在 Stack
类型之前声明一个模板运算符,然后声明为友元,即实例化。语法看起来有点别扭,但是看起来是这样的;
// forward declare the Stack
template <typename>
class Stack;
// forward declare the operator <<
template <typename T>
std::ostream& operator<<(std::ostream&, const Stack<T>&);
template <typename T>
class Stack {
friend std::ostream& operator<< <>(std::ostream& os, const Stack<T>& a);
// note the required <> ^^^^
void print(std::ostream& os, char ofc = ' ') const;
// ...
};
template <typename T>
std::ostream& operator<<(std::ostream&, const Stack<T>&)
{
// ... implement the operator
}
上面的代码将operator的friendship限定在Stack
对应的实例化中,即operator<< <int>
实例化仅限于访问Stack<int>
实例化的私有成员。
备选方案包括允许友谊扩展到模板的所有实例化;
template <typename T>
class Stack {
template <typename T1>
friend std::ostream& operator<<(std::ostream& os, const Stack<T1>& a);
// ...
};
operator<<
的实现可以在 class 定义内或外部内联完成。