2012-03-06 3 views
3

나는 현재 얻으려고 노력하고있는 컴파일하려면 다음(const를) 오버로드 된 메서드

class foo { 
}; 

class bar { 
public: 
    const foo & to_foo() const { 
    return f; 
    } 

    foo & to_foo() { 
    return f; 
    } 
private: 
foo f; 
}; 

template< typename T, typename Enable = void > 
class convert {}; 

template< typename T > 
struct convert< T, typename std::enable_if< std::is_member_function_pointer< decltype(&T::to_foo) >::value >::type > { 

    static const foo & call1(const bar & b) { 
    return b.to_foo(); 
    } 

    static foo & call2(bar & b) { 
    return b.to_foo(); 
    } 
}; 

그러나 그것은을 선택합니다, 그래서 두 가지 to_foo() 회원의 존재에 의해 혼동 전문화 GET의 기본 경우. to_foo() 멤버 중 하나를 제거하자마자 작동하지만, callX() 메서드 중 하나가 constness와 일치하지 않기 때문에 실패합니다.

이 경우이 기능을 감지 할 수있는 방법이 있습니까?

편집 : http://ideone.com/E6saX하여 방법 중 하나를 제거

, 그것은 잘 작동 : http://ideone.com/iBKoN

+1

그것은 당신이 여기 달성 하려는지 조금 불분명 : 참조하십시오. 'convert'의 사용법을 설명하면 문제를 해결하려는 현재의 시도에서 벗어나는 대신 달성하려는 것을 볼 수 있습니다. –

+0

@MatthieuM .: 여러 유형을 처리하는 훨씬 더 복잡한 대규모 프레임 워크의 일부입니다. 일부 유형의 경우 전환을 사용하기 전에 전환이 필요합니다. 그러나이 변환 된 형식을 변환하는 방법을 검색하는 방법이 필요합니다. 입력 형식에 크게 의존하기 때문입니다. 주어진 코드는 이것의 작은 부분으로, 현재 작동하려고합니다. – LiKao

답변

1

그것은 아직도 당신이 달성하려고하는 무엇을 나에게 조금 불분명하다. 대상 유형 (foo)이 고정되어 있으며 전체 브리지 시스템을 만들려고하지 않는다고 가정합니다.

이 경우 구조를 제거하고 과부하 선택에만 의존 할 수 있습니다.

foo const& to_foo(bar const& b) { return b.to_foo(); } 
foo& to_foo(bar& b) { return b.to_foo(); } 

실제로 번역이 진행되는 한 올바르게 작동합니다. 관련된 템플릿이 없습니다.

이제이 변환이 가능한지 여부를 확인하려면 을 실제로 확인하는 것이 좋습니다. 이 경우 변환을 시도하는 동안 오류가 발생하지 않도록 SFINAE를 사용해야합니다.

#include <iostream> 
#include <utility> 

// Didn't remember where this is implemented, oh well 
template <typename T, typename U> struct same_type: std::false_type {}; 
template <typename T> struct same_type<T, T>: std::true_type {}; 

// Types to play with 
struct Foo {}; 
struct Bar { Foo _foo; }; 
struct Bad {}; 

Foo const& to_foo(Bar const& b) { return b._foo; } 
Foo& to_foo(Bar& b) { return b._foo; } 

// Checker 
template <typename T> 
struct ToFoo { 
    T const& _crt; 
    T& _rt; 

    template <typename U> 
    static auto to_foo_exists(U const& crt, U& rt) -> 
     decltype(to_foo(crt), to_foo(rt), std::true_type()); 

    static std::false_type to_foo_exists(...); 

    // Work around as the following does not seem to work 
    // static bool const value = decltype(to_foo_exists(_crt, _rt))::value; 
    static bool const value = same_type< 
           decltype(to_foo_exists(_crt, _rt)), 
           std::true_type 
          >::value; 
}; 

// Proof 
int main() { 
    std::cout << ToFoo<Bar>::value << "\n"; // true 
    std::cout << ToFoo<Bad>::value << "\n"; // false 
} 

참고 : 성공적으로 gcc 4.5.1합니다 (주변의 일에) 연타 3.0에서 컴파일.

+0

아, 알겠습니다. 여분의 간접 지정은 오류가 발생하는 경우 도움이됩니다. 일단 지금은 한 메소드의 이름을 to_foo()에서 to_const_foo()로 변경하여이 문제를 해결했습니다. 그러나 이것은 두 가지 방법이 실제로 똑같은 일을하기 때문에 더 못생긴 해킹입니다. 그래서 그들은 같은 이름을 가져야합니다. 나는 당신의 방법을 채택 할 수 있는지 보겠습니다. – LiKao

0

나에 대해 잘 모르는 여기

는 ideone에 대한 예입니다 아직 템플릿이 있지만, 이 찾고있는 특성 인 것으로 보입니다. 기능이 const인지 확인합니다.

링크 here

+0

어려움이 있지만 메서드가 오버로드되어'T :: to_foo'를 추론 할 수 없습니다. 오버로드 된 메소드의 경우 올바른 서명에 대한 static_cast가 필요합니다. –

+0

아니요, is_const는 분명히 도움이되지 않습니다. 왜냐하면 저는 그 방법이 전혀 존재하지 않는지 알아 내려고하기 때문입니다. 나는 나중에 부분을 제외하고 const에 대해 정말로 신경 쓰지 않는다. const 클래스와 non-constness를 처리하는 부분으로'convert' 클래스를 나눠야 할 수도 있습니다 만, 이것은 오버로드 된 메소드의 존재를 감지하는 문제를 해결하지 못합니다. – LiKao

-1

내 gcc (4.1.0)는 C++ 0x를 지원하지 않으므로 std :: enable_if 부분을 제거합니다. 컴파일되고 성공적으로 실행됩니다. http://ideone.com/KzasX

감사