2014-11-03 3 views
2

다음 코드를는 SFINAE을 악용하기 - 컴파일 오류

#include <type_traits> 

struct CByteArray {}; 
struct HLVariant { 
    HLVariant() {} 
    HLVariant(const HLVariant&) {} 
    HLVariant(const CByteArray&) {} 

    }; 

template <typename T> 
inline typename std::enable_if<!std::is_pod<T>::value, CByteArray>::type serialize(const T& value) 
{ 
    return serialize(HLVariant(value)); 
} 

template <typename T> 
inline typename std::enable_if<std::is_pod<T>::value, CByteArray>::type serialize(const T& value) 
{ 
    return CByteArray(); 
} 

template <> 
inline CByteArray serialize(const HLVariant& value) 
{ 
    return CByteArray(); 
} 

int main() 
{ 
    serialize(0); 
    serialize(CByteArray()); 
    serialize(HLVariant()); 

    return 0; 
} 

그것은 않습니다, 그러나, ideone에서 작업 MSVC 2013 년 컴파일 오류 C2794: 'type' : is not a member of any direct or indirect base class of 'std::enable_if<false,CByteArray>' 트리거 : enter link description here

무엇을 실수로합니까?

오류는 MSVC 2010, 2012 및 2013

+4

나는 오류가 "MSVC 2013"인 내기 것입니다 :) – Pradhan

+0

@Pradhan : 당신은 MS 컴파일러는 다음 GCC에 어떻게 든 열등한 것을 의미하는 경우 당신은 진실에서 더 멀어 질 수 없습니다. –

+0

@VioletGiraffe C++ 언어 준수? MS 컴파일러는 약간 뒤쳐져 있습니다. 다른 장점이 있지만 C++ 언어 준수에 대해 스스로 괴롭히지 마십시오. MSVC 2013의 어떤 업데이트가 있습니까? – Yakk

답변

2

그것은 나에게 좋아 보이는에서 동일하지만, 나는 serialize의 최종 과부하에서 template<>을 제거하여 문제를 해결할 수 있습니다. 정상적인 과부하가 발생했을 때이를 전문화 할 필요가 없습니다!

EDIT : HLVariant과 일치하는 템플릿 전문화를 제공하고 (모호성을 피하기 위해 HLVariant과 더 이상 일치하지 않는 다른 전문화를 추가로 제한하는 작업).

이 그것을 수행해야합니다

http://ideone.com/0UGkcn

#include <type_traits> 
#include <iostream> 

struct CByteArray {}; 
struct NonPod {public: int a; private: int b;}; 
struct HLVariant { 
    HLVariant() {} 
    HLVariant(const HLVariant&) {} 
    HLVariant(const CByteArray&) {} 
    HLVariant(const NonPod&) {} 
}; 

template <typename T> 
inline typename std::enable_if<std::is_same<T, HLVariant>::value && !std::is_pod<T>::value, CByteArray>::type serialize(const T& value) 
{ 
    std::cout << "serialize non-pod variant\n"; 
    return CByteArray(); 
} 

template <typename T> 
inline typename std::enable_if<!std::is_same<T, HLVariant>::value && !std::is_pod<T>::value, CByteArray>::type serialize(const T& value) 
{ 
    std::cout << "serialize non-pod non-variant\n"; 
    return serialize(HLVariant(value)); 
} 

template <typename T> 
inline typename std::enable_if<std::is_pod<T>::value, CByteArray>::type serialize(const T& value) 
{ 
    std::cout << "serialize pod\n"; 
    return CByteArray(); 
} 

int main() 
{ 
    std::cout << "int:\n"; 
    serialize(0); 
    std::cout << "CByteArray:\n"; 
    serialize(CByteArray()); 
    std::cout << "HLVariant:\n"; 
    serialize(HLVariant()); 
    std::cout << "NonPod:\n"; 
    serialize(NonPod()); 
} 
+0

나는 당신이 거기에서 한 것을 본다. 문제는, 실제 과도한 코드에서는, 템플릿이 아닌 과부하가 우선시되고 (IIRC), 50 가지의 다른 방식으로 'HLvariant'가 생성 될 수 있기 때문에, 유형이 아닌 명시 적 생성자를 통해. 즉,'serialize'의 잘못된 버전이 호출 될 것입니다. –

+0

사용자 정의 변환은 템플릿 완전 일치보다 덜 일치해야합니까? – Yakk

+0

그래, 단지 'HLVariant'와 일치하는 템플릿 전문화를 원한다는 것과 (모호성을 피하기 위해'HLVariant'와 일치하는 다른 특수화를 방지하기 위해) 좋아합니다. 업데이트 할게 ... –