2012-11-20 1 views
5

일부 SFINAE 기능을 사용하고 있습니다. 현재 Linux 및 Windows에서 실행해야하는 응용 프로그램의 일부입니다. 컴파일러 선택 사항은 Windows 응용 프로그램 용 MSVC (Visual Studio 2010 10.0) 및 Linux 용 GCC 4.4.5입니다.특정 프로토 타입의 메소드가 클래스 안에 있는지 찾는 방법은 무엇입니까?

특정 개체가 사용자 지정 serialization을 수행하고이 함수를 호출하는 몇 가지 기능을 제공하는지 확인해야하며 사용자 지정 serialization 메서드가 제공되지 않는 반면 memcpysizeof(Object)은 간단합니다.

template 
    < 
     typename Type, 
     typename Return, 
     typename Parameter, 
     Return (Type::*Pointer)(Parameter) const 
    > struct sMemberMethodConst { }; 

template 
    < 
     typename Type, 
     typename Return, 
     typename Parameter, 
     Return (Type::*)(Parameter) 
    > struct sMemberMethod { }; 

template<typename T> struct sMemberMethodChecker 
{ 
    template <typename Type> static char HasCustomSizeMethod(sMemberMethodConst<Type, size_t, void, &Type::Size> *); 
    template <typename Type> static long HasCustomSizeMethod(...); 
    template <typename Type> static char HasSerializeMethod(sMemberMethodConst<Type, size_t, void * const, &Type::Serialize> *); 
    template <typename Type> static long HasSerializeMethod(...); 
    template <typename Type> static char HasDeserializeMethod(sMemberMethod<Type, size_t, const void * const, &Type::Deserialize> *); 
    template <typename Type> static long HasDeserializeMethod(...); 
    // Other specific method checks... 

    enum 
    { 
     HAS_CUSTOM_SIZE_METHOD = (sizeof(HasCustomSizeMethod<T>(0)) == sizeof(char)), 
     HAS_SERIALIZE_METHOD =  (sizeof(HasSerializeMethod<T>(0)) == sizeof(char)), 
     HAS_DESERIALIZE_METHOD = (sizeof(HasDeserializeMethod<T>(0)) == sizeof(char)), 
     IS_CUSTOM =     HAS_CUSTOM_SIZE_METHOD && 
            HAS_SERIALIZE_METHOD && 
            HAS_DESERIALIZE_METHOD, 
     // Other 'shortcuts'... 
    }; 

그리고 GCC로 컴파일하는 동안 내가지고있어 오류 : 코드 조각이 MSVC에서 경고 나 오류없이 컴파일하지만, GCC로 컴파일하는 동안, 코드는 다음과 같은 것을

문제는 경우 : struct sMemberMethodChecker의 첫 줄

invalid parameter type 'void' in declaration template<class Type, class Return, class Parameter, Return (Type::* Pointer)(Parameter)const>

. 나는 확실히 내가 누락되지 않았다고 확신한다. typename s 단어도 잘못 놓았지만 왜 나는 오류를 얻었는지 이해하지 못하고 오류를 이해하지 못한다.

은 내가 궁금하네요 그래서 GCC는 꽤 잘 표준을 준수하면서 문제가 바보 코드을 허용하는 MSVC 측에 거짓말을하면 MSVC 표준과 느슨한 것을 알고!

여기 질문입니다

  • 왜 내가 struct sMemberMethodCheckerinvalid parameter type 'void' 오류는 무엇입니까?.
  • 코드가 MSVC에서는 유효하지만 GCC에서는 유효하지 않은 이유는 무엇입니까?
  • 이 코드는 비표준입니까?
  • SFINAE 속임수가 C++ 11을 제외합니까?
+0

'const void * const'가 허용 되었습니까? 컴파일러에게 당신이'const void' 타입의 객체를 가지고 있다고 말하고 있습니다. 그러나 AFAIK는 공백을 수정할 수 없습니다. 'void * const'를 시도하면 어떻게됩니까? – RedX

+3

좋은 질문입니다. 그것은 GCC는'템플릿 수락하지 않는 것 같습니다 < 유형 이름 유형, 유형 이름 반환, 유형 이름 매개 변수를 반환 (유형 :: *) ('** 무효'**) > 구조체 sMemberMethod {};'등의 매개 변수 . 반면에 MSVC는 그것에 대해 자유 주의적입니다. – iammilind

+1

나는 iammilind가 옳다고 믿습니다. C와는 달리 C++은 함수의 인수 목록에'void '를 허용하지 않습니다. 그것은 C에서'f()'는 프로토 타입이없는 함수 (= 매개 변수는 지정되지 않음)이고 C++에서는'f()'가 인수가없는 함수이기 때문입니다. – Angew

답변

2

이유는 구조체 sMemberMethodChecker에서 유효하지 않은 매개 변수 유형 '무효'오류 받고 있어요?

코드가 MSVC에서 유효하지만 GCC에없는 이유는 무엇입니까?

나는 MSVC가 유용하지만 GCC가이 특정 코드에서 엄격하다고 믿습니다. 어떻게 든 그것을 허용하지 않기 때문에 Return (Type::*)(void). 그러나 정확한 이유를 알기 위해서는 더 많이 파고들 필요가 있습니다.

이 코드는 표준이 아닙니까?

컴파일 할 때까지 말할 수 없습니다. 그리고 SFINAE와 같은 기능에 대한 표준 검색은 모두의 차 한잔이 아닙니다.

SFINAE 속임수는 C++ 11을 제외합니까?

전혀 아닙니다. SFINAE는 C++ 11 이전에 존재했습니다.특정 유형의 멤버 메소드가 내부에 존재하거나하지 않을 경우

template<typename ClassName, typename ClassMethodType> 
struct HasMethod 
{ 
    template<typename Type, Type Object> struct Contains; 
    typedef char (&yes)[2]; 

    template<typename Class, typename MethodType> 
    static yes Check (Contains<MethodType, &Class::size>*); 
    template<typename Class, typename MethodType> 
    static char Check (...); 

    static const bool value = (sizeof(Check<ClassName,ClassMethodType>(0)) == sizeof(char)); 
}; 

HasMethod<ClassName, ClassMethodType>::value 당신에게 대답을 제공합니다 : 여기
은 당신이 원하는 무엇의 단순화 방법입니다. 지금 현재로 HasMethod<>
사용자 제공 유형size 명명 방법 배타적이다. 그러나 위의 코드에 대한 매크로를 만들고 함수 이름을 으로 만들 수 있습니다. 여기

working demo with g++이다.

+1

아주 좋은 답변입니다! 불행히도 예제 코드는 정확히 필요한 것은 아니지만 주된 문제를 해결하기 위해 안내해주었습니다. btw : 가난한 영어를 고쳐 주셔서 감사합니다.) –