سؤال

لدي فصل، معرف في رأس:

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&)

أنا من المفاجئ أن يكون المترجم ولن أنجوذا تلقائيا هذا بالنسبة لي ... أي اقتراحات حول ما أفعله خطأ؟

هل كانت مفيدة؟

المحلول

في ملف التنفيذ، لدي:

تلك هي المشكلة. لا يمكنك تقسيم تعريفات القوالب بين ملفات الرأس والتنفيذ. نظرا لطبيعة القوالب، تكون المحاميلات C ++ Finicky هنا. حدد كل الكود في الرأس لجعله يعمل.

في الواقع، المشكلة هنا هي أن جميع تعريفات القوالب يجب أن تقيم في نفس وحدة الترجمة نفسها لأن معيار 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