【问题标题】:Compiler not creating templated ostream << operator编译器未创建模板化 ostream << 运算符
【发布时间】:2010-10-07 18:15:03
【问题描述】:

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

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

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

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

【问题讨论】:

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


    【解决方案1】:

    在一个实现文件中,我有:

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

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

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

    【讨论】:

    • > 从理论上讲,C++ 标准定义了一个关键字 extern 来处理这些情况。我认为您正在考虑export,而不是外部。
    • 亲爱的我,多么明显的解决方案。树木的木材!
    【解决方案2】:

    模板太多 - 这行得通:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-17
      • 1970-01-01
      • 2023-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-21
      • 1970-01-01
      相关资源
      最近更新 更多