2016-12-28 19 views
2
#include <vector> 
#include <list> 
#include <iostream> 

template 
< 
    typename T, 
    template<typename, typename = std::allocator<T>> class C, 
    typename = std::enable_if_t 
    < 
    std::is_same<std::vector<T>, C<T>>::value 
    > 
> 
void f(const C<T>& coll) 
{ 
    std::cout << "vector" << std::endl; 
} 

template 
< 
    typename T, 
    template<typename, typename = std::allocator<T>> class C, 
    typename = std::enable_if_t 
    < 
    std::is_same<std::list<T>, C<T>>::value 
    > 
> 
void f(const C<T>& coll) 
{ 
    std::cout << "list" << std::endl; 
} 

int main() 
{ 
     std::vector<int> c1{ 1, 2, 3 }; 
     std::list<int> c2{ 1, 2, 3 };  
     f(c1); 
     f(c2); 
} 

연타 3.8 불평 :SFINAE가 std :: enable_if_t에서 작동하지 않는 이유는 무엇입니까?

오류 : 코드의 잘못 어떤 유형 이름 = 표준 : enable_if_t

: 템플릿 매개 변수는 기본 인수를 재정의?

+0

대신에 'enable_if_t * = nullptr'과 같은 형식이 아닌 템플릿 매개 변수를 사용하려 했습니까? –

+0

나는 그것을 시도했지만 그 결과는 동일하다. – xmllmx

+0

나는 non-type 템플릿 매개 변수와 함께 작동해야한다고 생각합니다. 이 코드는 부적절합니다 –

답변

1

SFINAE가 필요한 이유는 무엇입니까? 간단한 과부하로 충분합니다! 당신이 정말로 당신과 당신의 정의를 수정할 수 있습니다 (이 경우에 어떤 의미로) SFINAE를 사용하려면

template <typename T> 
void f(const std::vector<T>& coll) 
{ 
    std::cout << "vector" << std::endl; 
} 

template < typename T> 
void f(const std::list<T>& coll) 
{ 
    std::cout << "list" << std::endl; 
} 

int main() 
{ 
    std::vector<int> c1{ 1, 2, 3 }; 
    std::list<int> c2{ 1, 2, 3 }; 
    f(c1); 
    f(c2); 
} 

그리고 :

template 
< 
typename T, 
     template<typename, typename = std::allocator<T>> class C, 
     typename std::enable_if_t 
     < 
     std::is_same<std::list<T>, C<T>>::value 
     >* = nullptr 
    > 
void f(const C<T>& coll); 

왜 당신의 정의가 작동하지 않았다 여기에 이미 찾을 수 있습니다 : SFINAE working in return type but not as template parameter

+1

이것은 질문에 대답하지 않습니다. 왜 작동하지 않습니까? _ – skypjack

+0

@skypjack : 그것을 수정했습니다. 감사! 그래서 나는 그것을 중복으로 표시한다. – Klaus

2

기본 템플릿 매개 변수는 함수 일치에 참여하지 않습니다. 그것은 적절한 기능을 찾아하려고 할 때 컴파일러의 관점에서
는, 모두 다음 서명이 : 그 때문에의

template <typename T, template<typename, typename> class C, typename> 
void f(const C<T>& coll); 

f의 두 번째 정의는 실제로는 재정이다.

template<typename = void> 
void f() {} 

template<typename = char> 
void f() {} 

// ... 

f<>(); 

방법을 컴파일러 그림은 당신이 호출 할 f 수 :

는 최소한의 예를 고려?
코드에서 다소 차이가 있습니다.

enable_if_t을 반환 유형으로 이동하면 예상대로 작동합니다.
이 경우 대체는 오류 (sfinae 표현식에서 예상 한대로)로 인해 두 정의 중 하나를 제외합니다.

+0

C++ 11은 항상 non-type 템플릿 매개 변수를 디폴트 값으로 사용할 수 있기 때문에 항상 'enable_if_t'를 반환 유형 (생성자/변환 연산자)으로 이동할 수있는 것은 아닙니다. 하나지만 너의 설명이 너무 좋아. +1 –

+1

@WF 너의 의도를 알 겠어. 이 경우 반환 유형은 실행 가능한 솔루션이므로 그 이유를 언급했습니다. 그게 다야. ;-) – skypjack