c++ - 编译器不创建模板化的 ostream << 运算符

标签 c++ templates operator-overloading operator-keyword ostream

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

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;
}

这一切看起来都相当洁净。但是,当我尝试使用此运算符(即 std::cout << MyClass())时,出现以下链接器错误:

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

我很惊讶编译器没有自动为我生成这个……关于我做错了什么有什么建议吗?

最佳答案

In an implementation file, I have:

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

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

理论上,C++ 标准定义了一个关键字export 来处理这些情况。在实践中,没有编译器实现这一点(有一个异常(exception)?),并且无意更改这一点,因为成本/实用性权衡被认为不够好。

关于c++ - 编译器不创建模板化的 ostream << 运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/551156/

相关文章:

C++ 运算符重载和保护字段

c++ - 不同编译器之间的名称查找不一致

c++ - 为模板类重载 operator[] - C++

c++ - 有没有办法在我的通用功能路由器设计中支持 'const reference' 作为功能签名参数?

c++ - 隐式特化模板类而不使用 <>

c++ - 如何根据变量值惯用地调用 C++ 函数?

c++ - 模板类实例之间的类型转换

c++ - 我可以在 nlopt 中表示染色体吗?

c++ - LibVLC Demux 无法查看

c++ - SQLite C 接口(interface)不创建 sqlite_master 表