n0p*_*0pe 2 c++ linker templates operator-overloading
在你问之前,是的,函数是在我的模板类的标题中定义的.
这是以下相关部分Example.h:
template<class T, class J, const int X, const int Y>
class Example {
public:
friend std::ostream& operator<<(std::ostream& s, const Example<T,J,X,Y>& b);
}
template<class T, class J, const int X, const int Y>
std::ostream& operator<<(std::ostream& s, const Example<T,J,X,Y>& b) {
// stuff
}
Run Code Online (Sandbox Code Playgroud)
我是这样说的main.cpp:
void foo(Example<A,B,5,5>& b) {
std::cout << b;
}
int main() {
Example<A,B,5,5> b = Example<A,B,5,5>();
foo(b);
}
Run Code Online (Sandbox Code Playgroud)
编译时,我收到以下链接器错误:
Undefined symbols for architecture x86_64:
"operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, Example<A, B, 5, 5> const&)", referenced from:
foo(Example<A, B, 5, 5>&) in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [dist/Debug/GNU-MacOSX/consolehero] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2
Run Code Online (Sandbox Code Playgroud)
长话短说:
warning: friend declaration ‘std::ostream& operator<<
(std::ostream&, const Example<T, J, X, Y>&)’ declares a non-template function
Run Code Online (Sandbox Code Playgroud)
您的声明未声明模板函数,因为在实例化时,所有类型都已知.您稍后将其定义为模板函数,并且链接器非常混乱.最简单的方法是inline在类中定义运算符
template<class T, class J, const int X, const int Y>
class Example {
public:
friend std::ostream& operator<<(std::ostream& s, const Example& b)
{
// stuff here
}
};
Run Code Online (Sandbox Code Playgroud)
或者,使用
template<class T, class J, const int X, const int Y>
class Example {
public:
template<class T1, class J1, const int X1, const int Y1>
friend std::ostream& operator<<(std::ostream& s,
const Example<T1,J1,X1,Y1>& b);
};
template<class T1, class J1, const int X1, const int Y1>
std::ostream& operator<<(std::ostream& s, const Example<T1,J1,X1,Y1>& b) {
// stuff
}
Run Code Online (Sandbox Code Playgroud)
我发现第一种方法更具吸引力.请注意,这两种方法并不相同.在第一种情况下,operator<<为每个实例化生成一个非模板,而在第二种情况下,它operator<<是模板化的,因此只有在通过类型推导使用其类型的类型调用它时才会生成它.这是一个相当微妙的观点,我真的不知道什么时候会更喜欢更普遍的第二种方法而不是第一种方法.
PS:有关第一种方法,请参阅http://en.cppreference.com/w/cpp/language/friend 模板朋友操作员,以获得更多说明.引用它:
这样的运算符可以在类体中定义,它具有为每个T生成单独的非模板运算符<<的作用,并使该非模板运算符<<其Foo的朋友
所以,基本上,在类定义中
friend std::ostream& operator<<(std::ostream& s, const Example& b){}
Run Code Online (Sandbox Code Playgroud)
相当于
friend std::ostream& operator<<(std::ostream& s, const Example<T,J,X,Y>& b){}
Run Code Online (Sandbox Code Playgroud)