2012-01-26 2 views
3

는 다음 클래스 고려 :메서드 시그니처의 특정 인수의 유무에 템플릿 특수화를 적용 할 수 있습니까?

class MyClass 
{ 
public: 
    template<class T> typename T::result_type apply(T& func) 
    { 
    if (is_int()) 
    { 
     return func(int(0)); 
    } 
    return func(double(0)); 
    } 
    ... 
}; 

(코드는 정말 유용한 보이지 않는,하지만 내 지점을 증명하기 만 인위적인 샘플입니다)

어쨌든, 일반적인 펑이 같은 것입니다 :

struct MyFunc 
{ 
    typedef void result_type; 
    template<class V> void operator()(V) 
    { 
    // do something 
    } 
}; 

하나는과 같이 사용합니다 :

MyClass c; 
MyFunc f; 
c.apply(f); 

제 질문은 - MyClass::apply은 원래 하나의 외에 다른 약간의 버전의 functor 을 인식하도록 변경할 수 있습니다. 예를 들어 호출자 개체 참조가 다른 모든 매개 변수와 함께 전달 될 것으로 예상하는 경우 이 :

struct MyFuncEx 
{ 
    typedef void result_type; 
    template<class V> void operator()(const MyClass& caller, V) 
    { 
    // do something 
    } 
}; 

그래서, 다음의 코드도 컴파일 것 :

MyClass c; 
MyFunc f; 
c.apply(f); 
MyFuncEx f2; 
c.apply(f2); 

를 보너스로 나는 펑 모두 과부하 포함 된 경우 컴파일을 실패 다음 즉, 실패를 컴파일하고 싶습니다 :

struct MyFuncSmartAss 
{ 
    typedef void result_type; 
    template<class V> void operator()(V) 
    { 
    // do something 
    } 
    template<class V> void operator()(const MyClass& caller, V) 
    { 
    // do something 
    } 
}; 

... 

MyClass c; 
c.apply(MyFuncSmartAss()); 

그러나 긴 오버로드가 짧은 것보다 우선 순위를 갖는 한 그렇게 중요하지 않습니다.

+0

boost :: bind()는 친구입니다 –

+0

그리고 ??????????? – mark

+0

boost :: bind를 사용하면'operator()'의 단일 오버로드로 살 수 있고 두 번째 호출에서도 단일 인수 만 취하는'operator() '를 제공하기 위해 caller에 클로저를 만들기 위해 호출 사이트를 결정할 수 있습니다 케이스. –

답변

3

정말 C++ 11 여부에 따라 다릅니다.

class MyClass { 
private: 
    int _int; 
    double _double; 

public: 
    template <typename F> 
    auto apply(F& f) -> decltype(f(_int), f(_double)) { 
    if (is_int()) { return f(_int); } 
    return f(_double); 
    } 

    template <typename F> 
    auto apply(F& f) -> decltype(f(*this, _int), f(*this, _double)) { 
    if (is_int()) { return f(*this, _double); } 
    return f(_double) 
    } 

}; 

어떻게 작동합니까 :이 C++ 11 (*)의 과부하 문제를 해결해야합니까?

  • 부적절한 오버로드 제거 : decltype의 후행 반환 유형 사양은 평가되지 않은 컨텍스트를 만듭니다. 컴파일러는 표현식의 일반적인 과부하 해결을 수행하지만 유형에 대해서만 신경을 씁니다. 오류가 발생하는 경우합니다 (operator()f에 존재하지 않는), 우리는 SFINAE을 쳐서 모두 작업하는 경우 apply의이 오버로드는
  • 모호성을 폐기 : 모두 오버로드에 적합한 경우 (F 두 연산자를 제공하기 때문에) 다음 호출이 모호

(*) 나는 후행 리턴 형 사양의 정확성 및 this_arg의 더 구체적 사용에 대한 너무 잘 모르겠습니다. Clang 3.0 및 gcc 4.5.2 모두 오류가 발생했습니다. 이것은 주위에 일할 수 있습니다, 조금 더 자세한 정보를 얻으십시오. 이 해결 방법에 ideone 행동에

// first 
decltype(f(0), f(0.0)) 

// second 
decltype(f(std::declval<MyClass>(), 0), f(std::declval<MyClass>(), 0.0)) 

:

편집 : int/double 요구 사항을 처리합니다.

+0

나는이 후행 반환 유형에 'this'를 허용하지 않는다고 생각한다. 표준에 결함이있다. 그래도 나는 잘못 될 수 있습니다. – Xeo

+0

@Xeo : 아, 알았어. 한 가지 방법이나 다른 방법으로 인터넷 검색이 입증되지 않았다. 쓸모가 없어. :) –

+0

답을 이해하기 위해 C++ 11 기능 요약을 읽어야합니다. 분명히 지난 6 년 동안 많은 변화가있었습니다 ... – mark

관련 문제