我有一个类,在一个头定义为:

template <typename T> class MyClass
{
   template <typename U> friend std::ostream& operator<<(std::ostream& output, const MyClass<U>& p);
   public:
      ...
}

在一个实现文件,我有:

template <typename U> std::ostream& operator<<(std::ostream& output, const MyClass<U>& m)
{
   output << "Some stuff";
   return output;
}

所有看上去还算清净。然而,当我尝试使用该运营商(即性病::法院<< MyClass的()),我得到下面的连接错误:

Undefined symbols: std::basic_ostream<char, std::char_traits<char> >& operator<< <InnerType>(std::basic_ostream<char, std::char_traits<char> >&, MyClass<InnerType> const&)

我惊讶的编译器没有automagicially产生这对我来说...任何建议,我在做什么错了?

有帮助吗?

解决方案

  

在一个实现文件,我有:

这就是问题所在。你不能分割头和实现文件之间的模板定义。由于模板的性质,C ++编译器是挑剔这里。定义所有的代码在头,使其工作。

在事实上,这里的问题是,所有模板定义必须驻留在同一个编译单元内,因为C ++标准没有定义如何信息模板跨越不同的单元是共用的。这些单元由连接器缝合在一起,但泛型是在编译时(这较早),的链接时。

解决

理论上,C ++标准定义的关键字,export,来处理这些情况。在实践中,编译器实现这一点(有一个例外?),并没有打算改变这一点,因为成本/效用权衡不被认为不够好。

其他提示

有太多的模板 - 此作品:

#include <iostream>
using namespace std;
template <typename T> struct MyClass {

    friend ostream & operator << ( ostream & os, MyClass<T> & c ) {
        os << "MyClass\n";
        return os;
    }
};

int main() {
    MyClass <int> c;
    cout << c;
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top