friend, template und namespaces



  • Hallo,

    folgendes Problem beschäftigt mich: Ich möchte eine function template zum friend einer Klasse N::A machen:

    // forward declare A
    
    namespace N {
        class A;
    }
    
    // forward declare x
    
    template<typename T>
    void x(T, N::A& a);
    
    // declare A
    
    namespace N {
        class A {
            private:
                int id;
    
                template<typename T>
                friend void ::x(T, A&);
        };
    }
    
    // define x
    
    template<typename T>
    void x(T, N::A& a) {
        a.id = 20;
    }
    
    // use
    
    int main() {
        N::A a;
        ::x(0l, a);
    }
    

    Dies funktioniert aber mit gcc nicht.

    test.cc: In function ‘void x(T, N::A&) [with T = long int]’:
    test.cc:36:   instantiated from here
    test.cc:17: error: ‘int N::A::id’ is private
    test.cc:28: error: within this context
    

    Wenn ich x aber in ein Namespace M übersiedle, und Zeile 20 wie folgt ändere, dann funktionierts:

    friend void M::x(T, A&);
    

    Hat irgendwer einen Tipp wie ich das hinkriegen könnte das x im globalem Namespace bleibt?

    danke
    Peter



  • Hi, dein Problem ist folgendes:

    Erstens deklarierst du eine Funktion x hier:

    // forward declare x
    
    template<typename T>
    void x(T, N::A& a);
    

    Danach auch wieder hier:

    template<typename T>
                friend void ::x(T, A&);
    

    Würdest du hier:

    N::A a;
    ::x(0l, a);
    

    Das :: vor x weglassen, würdest du merken das dies Mehrdeutig ist.
    Das kommt durch den "Koenig-Lookups", der besagt falls man ein Argument N::A an eine Funktion übergibt, dass auch in N nach der Funktion geschaut wird, zudem gibt es auch nochmal die globale Funktion x;

    Lösung des Problems:
    -> // forward declare x weg
    -> template<typename T> friend void x(T, A&); // also ohne ::
    -> und bei der Def von x wieder N::x { definiton }

    Edit: Also so:

    namespace N {
        class A;
    }
    
    // declare A
    
    namespace N {
        class A {
            private:
                int id;
            public:
                template<typename T> friend void x(T, A&);
        };
    }
    
    // define x
    
    template<typename T>
    void N::x(T, N::A& a) {
        a.id = 20;
    }
    
    // use
    
    int main() {
        N::A a;
        x(0l, a);
    }
    


  • Hallo KasF,

    danke für die Antwort, es compiliert! Was mich allerdings wundert, ist wieso ich
    in main

    x(0l, a);
    

    aufrufen kann, wenn doch x im namespace N liegt:

    template<typename T>
    void N::x(T, N::A& a) { 
    ...
    

    Oder verstehe ich da was falsch?

    Peter



  • ubu_roi schrieb:

    x(0l, a);
    

    Wie schon erwähnt, hat das mit dem "Koenig Lookup" zu tun. Da dein Argument a vom Typ N::A ist, wird auch in N nach einer Funktion x gesucht.

    Näheres dazu hier: http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&faq=Koenig#Answ


Anmelden zum Antworten