2017-02-06 3 views
19

Comment find_type sait où est la fonction typemap?
L'argument qu'il reçoit ne provient pas de cet espace de noms, il provient de l'espace de noms std!Pourquoi cette mallette ADL fonctionne-t-elle?

#include <type_traits> 
#include <memory> 

namespace lib { 
    template<typename T> 
    struct find_type { 
     using type = decltype(typemap(std::declval<T>())); 
    }; 
} 

namespace test { 
    struct Test {}; 
    auto typemap(std::unique_ptr<Test>) -> int;  
} 

static_assert(std::is_same<int, lib::find_type<std::unique_ptr<test::Test>>::type>::value, ""); 

Comment ce code peut-il fonctionner? Quelle est la règle permettant cela? Je l'ai testé avec GCC 6.3 et 3.9.1.

+6

Le type de paramètre du paramètre de modèle 'T' de la structure' find_type' est 'std :: unique_ptr '. 'std :: unique_ptr' considère le paramètre template' test :: Test' pour ADL, et donc trouve la fonction 'typemap' dans le' test' NS – SebNag

Répondre

19

Dans le standard C++ N4618 §3.4.2 [basic.lookup.argdep] (2,2)

Si T est un type de classe (y compris les syndicats), les classes associées sont: la classe elle-même; la classe dont il s'agit un membre, le cas échéant; et ses classes de base directes et indirectes. Ses espaces de noms associés sont les espaces de noms englobants les plus internes de ses classes associées . En outre, si T est une spécialisation de modèle de classe, ses espaces de noms et classes associés incluent également: les espaces de noms et les classes associés aux types des arguments de modèle fournis pour les paramètres de type de modèle (à l'exclusion des paramètres de modèle modèle ); les espaces de noms dont les arguments du modèle de modèle sont membres; et les classes dont tous les modèles de membre utilisés comme arguments de modèle de modèle sont membres.

L'argument de typemap est std::unique_ptr<test::Test>, de sorte que l'espace de noms test est considéré pour le nom rechercher.

14

L'argument qu'il reçoit ne provient pas de cet espace de noms, il provient de l'espace de noms std!

Pas tout!

using type = decltype(typemap(std::declval<T>())); 

C'est:

using type = decltype(typemap(std::declval<std::unique_ptr<test::Test>>())); 

Il y a un test:: là-dedans, de sorte que l'espace de noms test est recherché aussi.