Wie trennt man Deklaration und Definition von friend-member-template-Funktionen?



  • Yeequ schrieb:

    Ich bin vor 15 Minuten auch darauf gekommen, daß die Priorisierung der stärker spezialisierten Form innerhalb der Template-Klasse der Grund ist, warum man nur noch alle Spezialisierungen einzeln von Hand angeben kann und das ganze nicht mehr generisch machen kann. An die Priorisierung hatte ich in diesem Fall nicht gedacht. Steht aber genau so unter ISO 14882:2003 Abschnitt 14.5.3.1 beschrieben.

    Okay., es kann an dieser Stelle überhaupt nichts mit der Priorisierung von Templatespezialisierungen zu tun haben. Eine normale Friendfunktion ist an dieser Stelle ja auch kein Template.


  • Mod

    Yeequ schrieb:

    Priorisierung von Templatespezialisierungen

    So etwas gibt es auch nicht, bzw. der Begriff ist so unscharf, dass ich nichts damit anfangen kann.

    Yeequ schrieb:

    Eine normale Friendfunktion ist an dieser Stelle ja auch kein Template.

    Ich kann nicht folgen.



  • camper schrieb:

    Yeequ schrieb:

    Priorisierung von Templatespezialisierungen

    So etwas gibt es auch nicht, bzw. der Begriff ist so unscharf, dass ich nichts damit anfangen kann.

    Yeequ schrieb:

    Eine normale Friendfunktion ist an dieser Stelle ja auch kein Template.

    Ich kann nicht folgen.

    Sorry. Ich habe gerade nicht genau nachgedacht als mir das eingefallen ist. Ich war gerade nebenbei mit etwas anderem beschäftigt. Das tut mir Leid.
    Also es gibt schon eine Priorisierung bei der Templatespezisierung allerdings gibt es Spezialisierung nur für Template-Klassen, nicht für Funktionen:

    template <typename T> class iterator {};
    template <typename T*> class iterator {};
    

    Ich weiß nur halt gerade immer noch nicht genau, warum man zwar die Varianten einzeln definieren kann

    template <typename T>
    struct Foo
    {
        template<typename S>
        friend S& operator<<(S& os, const Foo& rhs);
    };
    template<typename S>
    S& operator<<(S& os, const Foo<int>& rhs) { /* ... */ }
    template<typename S>
    S& operator<<(S& os, const Foo<float>& rhs) { /* ... */ }
    

    Aber eben nicht nochmal irgendwie als Template bzw. warum genau dann stets der Linkage Fehler kommt.

    Mir war nur gerade wieder folgendes in den Sinn gekommen, wie man Template-Funktionen befreundet, die außerhalb der Klasse definiert sind, worauf mir der Gedanke kam, irgendwie könnte das ja vielleicht auch in dem ursprünglichen Fall so ähnlich gehen.

    template <typename T>
    void func0(Test<T> x) {
        std::cout << "func0: " << x.value_ << std::endl;
    }
    
    template <typename T>
    class Test {
        public:
            Test(const T& value) : value_(value) {}
            friend void func0<>(Test);
        private:
            T value_;
    };
    

  • Mod

    Yeequ schrieb:

    Ich weiß nur halt gerade immer noch nicht genau, warum man zwar die Varianten einzeln definieren kann

    template <typename T>
    struct Foo
    {
        template<typename S>
        friend S& operator<<(S& os, const Foo& rhs);
    };
    template<typename S>
    S& operator<<(S& os, const Foo<int>& rhs) { /* ... */ }
    template<typename S>
    S& operator<<(S& os, const Foo<float>& rhs) { /* ... */ }
    

    Aber eben nicht nochmal irgendwie als Template bzw. warum genau dann stets der Linkage Fehler kommt.

    Überleg einfach mal, welches Verhältnis zwischen

    template<typename T> void foo(T, int);
    

    und

    template<typename T, typename U> void foo(T, U);
    

    besteht? Spezialisierung? Überladung? Etwas anderes?



  • camper schrieb:

    Yeequ schrieb:

    Ich weiß nur halt gerade immer noch nicht genau, warum man zwar die Varianten einzeln definieren kann

    template <typename T>
    struct Foo
    {
        template<typename S>
        friend S& operator<<(S& os, const Foo& rhs);
    };
    template<typename S>
    S& operator<<(S& os, const Foo<int>& rhs) { /* ... */ }
    template<typename S>
    S& operator<<(S& os, const Foo<float>& rhs) { /* ... */ }
    

    Aber eben nicht nochmal irgendwie als Template bzw. warum genau dann stets der Linkage Fehler kommt.

    Überleg einfach mal, welches Verhältnis zwischen

    template<typename T> void foo(T, int);
    

    und

    template<typename T, typename U> void foo(T, U);
    

    besteht? Spezialisierung? Überladung? Etwas anderes?

    Also wenn ich diese letzten zwei Funktionen untereinander sehe, dann wird mir auch sofort bewußt, daß die friend-temlate-Deklaration eine Funktion von erstem Muster in die Funktionstabelle einträgt, wohingegen die zweite Funktion zwei Template-Argumente hat. Die Overload Resolution wählt dann natürlich die erste Funktion aus, die aber nicht definiert ist.

    Eigentlich ist es sehr einfach, wenn man seine Gedanken richtig ordnet.


Anmelden zum Antworten