2016-11-05 2 views
0

Je tente de résoudre this question.C++ 17, pourquoi ne pas auto non-type paramètre de modèle de travail avec SFINAE

Dans mon code ci-dessous, je souhaite utiliser FunctionInfo pour détecter la surcharge d'une fonction choisie par sa liste de paramètres.

Avec:

decltype(MethodInfo<Foo, int>::get(&Foo::foo)) 

Je peux choisir la fonction de surcharge correcte en fonction de la liste des paramètres.

Je veux aller plus loin 1 pour pouvoir utiliser:

FunctionInfo<Foo, std::tuple<int>, &Foo::foo>::type 

Mais quand j'ai essayé avec la solution ci-dessous, clang dans la tête 4.0.0 rapport ceci:

error: non-type template parameter 'f' with type 'auto' has incompatible 
    initializer of type '<overloaded function type>' 
FunctionInfo<Foo, std::tuple<int>, &Foo::foo>::type 
            ^~~~~~~~~ 

Mon question est pourquoi SFINAE n'implique pas de choisir quelle fonction est appropriée.

#include <type_traits> 
#include <tuple> 

template<typename T, typename... Args> 
struct MethodInfo { 
    template<typename Ret> 
    static auto get(Ret(T::*)(Args...)) -> Ret(T::*)(Args...); 
}; 

template<typename T, typename Tuple> 
struct MethodInfoFromTuple; 

template<typename T, typename...Args> 
struct MethodInfoFromTuple<T, std::tuple<Args...>>{ 
    using type = MethodInfo<T, Args...>; 
}; 

template<typename T, typename ArgPack, auto f, 
      typename Func = decltype(MethodInfoFromTuple<T, ArgPack>::type::get(f))> 
struct FunctionInfo { 
    using type = Func; 
}; 

struct Foo { 
    int foo(int); 
    // Uncomment this line then only first static_assert work 
    // int foo(int, int); 
}; 

int main() { 
    static_assert(std::is_same< 
         int(Foo::*)(int), 
         decltype(MethodInfo<Foo, int>::get(&Foo::foo)) 
          >::value, ""); 
    static_assert(std::is_same< 
         int (Foo::*)(int), 
         FunctionInfo<Foo, std::tuple<int>, &Foo::foo>::type 
          >::value, ""); 

} 

Répondre

1

Les ensembles de surcharge ne sont pas des valeurs en C++. Les arguments de type non-type sont des valeurs.

Les ensembles de surcharge sont résolus à des valeurs dans un ensemble restreint de circonstances, en utilisant des règles spécifiques. Ces règles ne sont pas "essayer chaque possibilité et s'il y a plus d'une possibilité légale, générer une erreur". Au lieu de cela, il y a des cas où des correspondances exactes sont choisies, et d'autres où un ordre sur les surcharges viables est fait et s'il n'y a pas d'égalité, "le meilleur" est choisi.

Le cas où vous passez à auto n'est ni l'un ni l'autre.

+0

Quel cas est "où une commande sur les surcharges viables est fait et s'il n'y a pas d'égalité"? – Danh

+0

@danh Quand vous l'appelez, et il choisit quelle surcharge. Lorsque vous le passez à un pointeur de fonction/méthode correspondant, la correspondance exacte est effectuée. – Yakk

+0

cela signifie que pour 'auto' dans le paramètre de modèle, une correspondance exacte est effectuée, pas de surcharge, ou en utilisant SFINAE pour choisir la surcharge sera effectuée? – Danh