friend Operator Linkerfehler



  • Hi,

    warum erzeugt dieser Code einen Linkerfehler?

    template<typename Val>
    class Size
    {
    public:
    	friend bool operator==(const Size<Val> &lhs, const Size<Val> &rhs);
    };
    
    template<typename Val>
    bool operator==(const Size<Val> &lhs, const Size<Val> &rhs)
    {
    	return true;
    }
    
    typedef Size<float> SizeF;
    
    int main()
    {
    	SizeF s, s2;
    	bool x = s == s2;
    }
    

    Der GCC hat dann als Hinweis ausgegeben, dass es mit

    friend bool operator==<>(const Size<Val> &lhs, const Size<Val> &rhs)
    

    geht. Warum sind hier die <> erforderlich?



  • Weil es sonst nicht als Template Funktion erkannt wird



  • so ungefähr müßte es eigentlich gehen:

    template<typename Val>
    class Size
    {
    public:
        template<typename Val_>
        friend bool operator==(const Size<Val_> &lhs, const Size<Val_> &rhs);
    };
    
    template<typename Val>
    bool operator==(const Size<Val> &lhs, const Size<Val> &rhs)
    {
        return true;
    }
    
    typedef Size<float> SizeF;
    
    int main()
    {
        SizeF s, s2;
        bool x = s == s2;
    }
    

  • Mod

    warum erzeugt dieser Code einen Linkerfehler?

    Weil du in der Klasse eine Funktion deklarierst, die natürlich nicht definiert ist. Nur das Funktionstemplate außerhalb. Name Lookup findet aber deine Funktion zuerst. Und das führt zum Linkerfehler.

    Kralo hat Recht:

    §14.5.4 schrieb:

    For a friend function declaration that is not a template declaration:
    — if the name of the friend is a qualified or unqualified template-id, the friend declaration refers to a specialization of a function template, otherwise
    [...]
    — the name shall be an unqualified-id that declares (or redeclares) an ordinary (non-template) function.

    Entweder du gibst eine template-id an, oder die Funktion die du deklarierst darf auf kein Funktionstemplate verweisen.

    Nun ist aber das Problem, dass die template-id nicht auf eine nicht deklarierte Funktion verweisen darf - denn sie deklariert selbst nichts. Lösung:

    template<typename> class Size; // Vorwärtsdeklaration
    template<typename Val> bool operator==(Size<Val> const& lhs, Size<Val> const& rhs);
    
    template<typename Val>
    class Size
    {
    public:
        // Damit wird jede Spezialisierung Size<Val> genau den Freund operator==<Val> haben
        friend bool operator==<Val>(const Size<Val> &lhs, const Size<Val> &rhs);
    };
    
    template<typename Val>
    bool operator==(const Size<Val> &lhs, const Size<Val> &rhs)
    {
        return true;
    }
    
    int main()
    {
        Size<float> s, s2;
        s == s2;
    }
    

    Jedoch ist die Methode von dd++ natürlich ein wenig kürzer. Dafür ist die Kapselung stärker gebrochen(!).



  • Ja, die <> bzw jetzt <Val> Version gefällt mir auch besser. Danke für eure Hilfe.


  • Mod

    KN4CK3R schrieb:

    Ja, die <> bzw jetzt <Val> Version gefällt mir auch besser. Danke für eure Hilfe.

    Du kannst auch <> verwenden. Dann werden die Template-Argumente automatisch deduziert.



  • Ich versteh genau Bahnhof. Was macht <T> besser als <>? Beispiel bitte.
    Bisher wusste ich gar nicht, dass <T> an der Stelle ueberhaupt erlaubt ist.


Anmelden zum Antworten