2015-01-20 5 views
0

SFINAE를 이해하려고 노력하고 있는데 그 중 어떤 클래스에 대해서도 'print'메서드를 호출하는 간단한 오버로드 된 연산자 < <을 작성하려고했습니다. 방법. 나는 질문 Is it possible to write a template to check for a function's existence?에 대한 답변을 통해 읽기 및 쓰기 시도 :SFINAE 오버로드 연산자 << 존재하는 경우 'print'메서드를 호출합니다.

template<class T, class = decltype(void(std::declval<T>().print), std::true_type{})> 
inline std::ostream &operator<<(std::ostream &out, const T &obj) { 
    obj.print(out); return out; } 

template<class T, class = decltype(void(std::declval<T>().print(std::declval<std::ostream &>())), std::true_type{})> 
inline std::ostream &operator<<(std::ostream &out, const T &obj) { 
    obj.print(out); return out; } 

을하지만 이것은 단순히 작동하지 않습니다 - 컴파일러는 모든 유형의 템플릿을 인스턴스화 아무런 문제가 없을 것 같다 따라서 문자열 리터럴과 같은 것을 인쇄하려고 할 때 '모호한 오버로드'오류가 발생합니다 ...

+0

왜 그런 방법이 필요합니까? 'print()'함수를 표준 인'operator <<'로 단순히 "이름을 변경"해야합니다. –

+0

관련이 없지만'inline'과 같은 템플릿을 선언 할 필요는 없습니다. 암시적일 것이다. – 5gon12eder

+0

@JohnZwinck :'print'가 가상 일 경우 작동하지 않습니다. (보통 경우) –

답변

1

"함수가 있습니다"라는 표현이 잘못되었습니다. 이 시도 : 당신은이 대안을 고려해 볼 수 있습니다

template <typename T, 
      typename = decltype(
       void(std::declval<T>().print(std::declval<std::ostream&>())), 
        std::true_type{})> // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
std::ostream & operator<<(std::ostream & out, const T & obj) 
{ 
    obj.print(out); 
    return out; 
} 

:

template <typename T> 
auto operator<<(std::ostream & out, const T & obj) 
    -> decltype(obj.print(out), (void)0, out) 
{ 
    obj.print(out); 
    return out; 
} 
+0

[데모] (http://ideone.com/yclfpX) –

+0

[두 번째 데모] (http://ideone.com/0unxAI) –

+0

두 번째 버전은 우아 해 보이지만'print'의 반환 유형에 오버로드 된 연산자','가 있으면 문제가되지 않습니다. 'void'로 변환하면이 문제를 해결할 수 있는지 확실하지 않습니다. – 5gon12eder

0

나는 당신이 의미하는 두 번째 유형 매개 변수

class = decltype(void(std::declval<T>().print), std::true_type{}) 

을 의미 한 것을 이해하지 않습니다. 이게 뭐야?

다음과 같이하면 효과가 있다고 생각합니다.

#include <iostream> 
#include <type_traits> 

template<typename T, 
     typename = decltype(std::declval<const T>().print(std::cout))> 
std::ostream& 
operator<<(std::ostream& out, const T& obj) 
{ 
    obj.print(out); 
    return out; 
} 

struct A 
{ 
    void 
    print(std::ostream& out) const 
    { 
    out << "A"; 
    } 
}; 

int 
main() 
{ 
    A a {}; 
    std::cout << "And the winner is: " << a << std::endl; 
} 

그것은 것이다 And the winner is: A 정확하게 출력하지만 간과 한 어떤 코너의 경우 아마이 있습니다.

같은 함수가 선언되면

decltype(std::declval<const T>().print(std::cout)) 

print(std::ostream&) const 멤버 함수의 리턴 형으로 계산하는 표현식과 달리 입력 오류.

+0

쉼표 앞에있는 부분이 유효한 포인터 유형 (print 메소드가있는 경우)으로 평가되는 경우에만 true 유형으로 평가되고 무시됩니다. –