2016-04-04 5 views
2

den Code Siehe unten:eine Funktion in einem anderen Namensraum als die ADL definieren, „local“ oder globalen Namensraum

#include <iostream> 

/// Definition of void perform(a_lib::a_class&). Where should I put this definition? 
/// See the comments below for where I've tried placing it. 
// void perform(a_lib::a_class&) { 
// std::cout << "performing on a_lib::a_class" << std::endl; 
// } 

namespace a_lib { 
    class a_class { }; 

    // WORKS HERE but it pollutes a_lib (namespace of third-party library). 
} 

namespace mine { 
    // DOESN'T WORK HERE: "use of undeclared identifier 'perform'". 
} 

// WORKS HERE but it pollutes the global namespace. 

namespace b_lib { 
    // WORKS HERE but it pollutes b_lib (namespace of third-party library). 

    template <typename Type> 
    void b_func(Type& obj) { 
    perform(obj); 
    } 
} 

namespace mine { 
    // DOESN'T WORK HERE: "use of undeclared identifier 'perform'". 

    void run() { 
    a_lib::a_class a_obj; 
    b_lib::b_func(a_obj); 
    } 
} 

int main(int, char**) { 
    mine::run(); 

    return 0; 
} 

a_lib und b_lib sind Namespaces zwei Bibliotheken verschiedener Drittanbieter gehören. mine ist mein eigener Namensraum.

Ich habe gelernt, dass es eine schlechte Idee ist, den globalen Namensraum zu verschmutzen und in this question sie auch sagen, dass das Hinzufügen von Typen zu std eine schlechte Idee ist. Ich denke, Letzteres gilt für Namespaces im Allgemeinen; Sie sollten keine Typen zu einem Namespace hinzufügen, der nicht Ihnen gehört.

Aber wie ich werde ich das Problem lösen, oben ohne diese Prinzipien zu brechen? Wo sollte ich die Definition perform() setzen und wie bekomme ich b_func(), um es zu nennen?

Kontext: Ich versuche, einen externen cereal serialize() für einen SFML Typ in meinem eigenen Namespace hinzuzufügen. Dies ist ein reduziertes Beispiel.

+0

Um die Schnittstelle von 'a_lib erweitern :: a_class' Sie die Dinge auf diese Art Namensraum hinzufügen sollten. Ob es eine gute Idee ist, die Schnittstelle von Typen zu erweitern, die Sie nicht besitzen (z. B. indem Sie sie serialisierbar machen), ist die Schlüsselfrage, aber wenn Sie das tun, sollten Sie dies im Namespace des Typs tun. Eine weitere Möglichkeit besteht darin, in Ihrem eigenen Namespace einen eigenen Typ zu definieren, der von 'a_class' abgeleitet ist, und die Serialisierungsunterstützung in Ihrem Namespace hinzuzufügen. –

+0

* "Ob es eine gute Idee ist, die Schnittstelle von Typen zu erweitern, die Sie nicht besitzen (z. B. durch Serialisierung), ist die Schlüsselfrage" * Das ist ein wirklich guter Punkt. Ich werde stattdessen von 'a_class' abgeleitet. Vielen Dank. – haisareisa

Antwort

0

Sie müssen angeben, wo der Compiler bei der Verarbeitung von "b_func" das "ausführen" finden kann.

Da "mein" ein Namespace ist, kann ein vollständigerer Name die Namensräume "erreichen".

Beachten Sie, dass bei der Implementierung von mir :: perform() auch "Type" definiert sein muss, um das obj zu verwenden.

+1

Wenn ich dich richtig verstanden habe, schlägst du vor, dass ich die Definition von 'b_func()' bearbeite. Das Problem ist, dass es Teil einer Bibliothek eines Drittanbieters ist und ich daher seine Definition nicht bearbeiten sollte. – haisareisa

+0

Wenn Sie b_func nicht ändern können, muss b_func() gerade eine "perform()" -Methode/Funktion aufrufen, die bereits existiert. Der Name suggeriert "perform" ist bereits global und kann daher nicht mehr "Verschmutzung" hinzufügen. –

+0

Nein, schlägt das nicht vor. Vermutlich ruft es die Funktion unqualifiziert auf, damit sie von ADL gefunden wird, um eine Funktion zu finden, die in den zugehörigen Namespaces von 'a_lib :: a_class' definiert ist. –