2012-08-17 2 views
6

다음 코드는 컴파일되지 않습니다. 이 인수 템플릿 메서드 enable_if 특수화

typename std::enable_if<std::is_void<Ret>::value, Ret>::type _on_dispatched() { 
    // ... 
} 

typename std::enable_if<!std::is_void<Ret>::value, Ret>::type _on_dispatched() { 
    // .... 
} 

내가 징벌이 무엇인지 유형에 따라 멤버 방법에 전문성을 갖고 싶어 소요 템플릿 클래스에서 두 가지 기능이 있습니다.

아무도 아이디어가 있습니까?

답변

7

SFINAE는 템플릿이 아닌 함수 (멤버 또는 비 멤버)에서는 작동하지 않습니다.

Kerrek SB가 지적했듯이 Kerrek SB가 비회원 함수 템플릿을 만들면 작동합니다. 또는 Xeo가 지적한대로 기본 템플릿 인수가있는 멤버 함수 템플릿을 만들 수도 있습니다.

그러나 두 개의 std::enable_if 조건이 비 중복이기 때문에 이것은 작동합니다. int (말하기)에 다른 과부하를 추가하려는 경우 잘 확장되지 않습니다.

#include<type_traits> 

template<typename Ret> 
class Foo 
{ 
public: 
    void _on_dispatched() 
    { 
     // tag dispachting: create dummy of either std::false_type or std::true_type 
     // almost guaranteed to be optimized away by a decent compiler 
     helper_on_dispatched(std::is_void<Ret>()); 
    } 

private: 
    void helper_on_dispatched(std::false_type) 
    { 
     // do stuff for non-void 
    } 

    void helper_on_dispatched(std::true_type) 
    { 
     // do stuff for void 
    } 
}; 

int main() 
{ 
    Foo<void>()._on_dispatched(); 
    Foo<int>()._on_dispatched(); 
    return 0; 
} 
+1

할 수 있습니다, 오버로드 중 하나는 통화 시간에 유일하게 가능한 한 경우. :) http://liveworkspace.org/code/fd6e5383610d4e0d8fb17c5497991355 – Xeo

+1

@Potatoswatter : 사실, 아니, 농담이 아니 었어. 링크를 참조하십시오. 반환 유형 만 실행 가능 여부를 결정하는 경우 정확히 동일한 서명의 함수를 완벽하게 작성할 수 있습니다. : P 또한'std :: is_void ()'을 사용하면'std :: true_type' 또는'std :: false_type'에서 파생되어야하는 형질이 필요합니다. – Xeo

+1

Btw, [멤버 함수를 C++ 11의 기본 매개 변수가있는 템플릿으로 만들 수 있습니다] (http://liveworkspace.org/code/781d94df5499998947217970c1aebf2a). – Xeo

3

SFINAE은 템플릿에서 작동합니다 : 당신이 원하는 무슨에 따라 태그 파견은 일반적으로 당신이 파견 할 여러 대안과 SFINAE보다 더 확장 할 수 있습니다. 귀하의 코드는 작은 수정과 컴파일 할 수있다 :

template <typename Ret> 
typename std::enable_if<std::is_void<Ret>::value, Ret>::type _on_dispatched() { /*...*/ } 

template <typename Ret> 
typename std::enable_if<!std::is_void<Ret>::value, Ret>::type _on_dispatched() { /*...*/ } 

사용법 : 그것은 추론 될 아니기 때문에

auto q = _on_dispatched<int>(); 

당신은 물론, 함수의 반환 유형을 추론 할 수 없습니다. 그러나 내부에 다른 템플릿을이 템플릿 팩을 할 수

template <typename T> 
struct Foo 
{ 
    // insert templates here, maybe privately so 

    T bar() { return _on_dispatched<T>(); } 
}; 
+0

'template '멤버 함수에 대해서는 rhalbersma의 대답에 대한 내 의견을 참조하십시오. – Xeo

+0

@Xeo : ''이라고 쓰지 않아도됩니다. 물론, 왜 :-) –