2016-11-05 5 views
0

this question을 해결하려고합니다.C++ 17, SFINAE에서 자동 비 형식 템플릿 매개 변수가 작동하지 않는 이유

아래 코드에서 FunctionInfo을 사용하여 해당 매개 변수 목록에서 선택한 함수의 오버로드를 감지하고 싶습니다.

으로 :

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

나는 매개 변수 목록을 기반으로 올바른 과부하 기능을 선택할 수 있습니다.

내가 사용할 수 있도록 한 단계 더 가고 싶어 :

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 
            ^~~~~~~~~ 

내 :

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

을하지만 HEAD에서 아래의 솔루션, 그 소리 4.0.0 보고서이 함께 시도 할 때 질문은 SFINAE가 어떤 기능이 적합한 지 선택하지 않는 이유입니다.

#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, ""); 

} 

답변

1

오버로드 집합은 C++의 값이 아닙니다. 템플릿 비 형식 인수는 값입니다.

오버로드 집합은 특정 규칙을 사용하여 좁은 집합의 값으로 결정됩니다. 이러한 규칙은 "각 가능성을 시도하고 둘 이상의 법적 가능성이있는 경우 오류를 생성합니다". 대신 정확한 일치가 선택되는 경우와 실행 가능한 과부하에 대한 순서가 수행되는 경우와 일치가없는 경우 "최고"가 선택되는 경우가 있습니다.

auto로 전달하는 경우도 마찬가지입니다.

+0

"가능한 부하에 대한 주문이 완료되고 타이가없는 경우"는 어떤 경우입니까? – Danh

+0

@danh 전화를 걸면 과부하가 발생합니다. 일치하는 함수/메소드 포인터에 전달하면 정확한 일치가 수행됩니다. – Yakk

+0

템플릿 매개 변수의'auto'에 대해 정확한 일치가 수행되고, 과부하가 없으며 SFINAE를 사용하여 과부하가 수행된다는 것을 의미합니까? – Danh