2017-04-19 1 views
8

Ich habe einige Zeit versucht zu realisieren, warum mein Code nicht kompiliert und ich habe festgestellt, dass in C++ Argument abhängige Lookup Vorlage Typname verwendet Argumente, um den Namen-Lookup-Bereich zu bestimmen.Was ist der Grund hinter ADL für Argumente, deren Typ ist eine Klassenvorlage Spezialisierung

#include <string> 
#include <functional> 

namespace myns { 

    template<typename T> 
    struct X 
    {}; 

    template<typename T> 
    auto ref(T) -> void 
    {} 

} // namespace myns 

auto main() -> int 
{ 
    ref(myns::X<int>{}); 
    ref(myns::X<std::string>{}); // error: call to 'ref' is ambiguous 
} 

So der ehemalige ref Aufruf kompiliert, weil für myns::X<int> nur myns::ref betrachtet wird, während die letzteren nicht kompilieren, weil es myns::ref() sowie std::ref

Meine Frage findet, ist, wie das sein kann sinnvoll? Warum sollte ich das brauchen? Hast du irgendwelche Ideen, Beispiele? Für den Moment sehe ich nur Nachteile wie im obigen Beispiel, wo unnötige Mehrdeutigkeiten entstehen.

+0

Benötigen Sie Ihre Funktion, um * irgendeinen * Typ zu akzeptieren? Andernfalls wäre 'auto ref (X ) -> void' eine bessere Übereinstimmung als' std :: ref' und wird durch die Überladungsauflösung ausgewählt. –

+0

Leider ja, tue ich. – witosx

Antwort

7

Angenommen, Sie fügen alle Dinge in Ihren eigenen Namespace ein, einschließlich einer benutzerdefinierten Klasse und einer Funktion, die std::vector als Parameter verwendet. dh

namespace myns { 

    struct X {}; 

    template<typename T> 
    auto my_func(const std::vector<T>&) -> void 
    {} 

} // namespace myns 

dann können Sie die Vorteile aus der Tatsache ziehen, dass ADL auch die Typen betrachtet als Vorlage Argumente zur Verfügung gestellt und schreiben Sie einfach:

my_func(std::vector<myns::X>{}); 

auf der anderen Seite:

my_func(std::vector<int>{});  // error, can't find my_func 
myns::my_func(std::vector<int>{}); // fine 

Zurück zu Ihrer ursprünglichen Frage, die Lektion hier ist, verwenden Sie keine Namen aus Standardbibliotheken Es macht Codes nur verwirrend.

3

In einem Wort: Wiederverwendung. Es ermöglicht Ihnen, nützliche Komponenten aus anderen Bibliotheken zu verwenden und dennoch ADL angewendet zu haben.

Zum Beispiel:

namespace my_stuff { 
    class my_class { 
    // Something useful here 
    }; 

    void process(std::unique_ptr<my_class> item); 
} 

Jetzt können Sie Code natürlich schreiben, wie Sie es, wenn es mit der Klasse arbeiten direkt:

process(std::make_unique<my_class>()); 

Wenn es nicht der Fall ist, würden Sie brauchen um deinen eigenen Smart Pointer in deinem eigenen Namespace einzuführen, nur um gute Codierungs-Idiome und ADL zu ermöglichen.

Verwandte Themen