Pracuję z niektórymi funkcjami SFINAE; obecnie w części aplikacji, która musi działać w systemie Linux i Windows; wybór kompilatora to MSVC (Visual Studio 2010 10.0) dla aplikacji Windows i GCC 4.4.5 dla Linuksa.Jak ustalić, czy w klasie istnieje metoda określonego prototypu?
Muszę sprawdzić, czy dany obiekt udostępnia niektóre funkcje do przeprowadzania niestandardowej serializacji i wywoływania tych funkcji, lub wykonać prosty memcpy
i sizeof(Object)
, podczas gdy niestandardowe metody serializacji nie są dostępne.
Problemem jest to, że kawałek kodu skompilować bez ostrzeżeń ani błędów w MSVC ale podczas kompilacji z GCC, kod jest następujący:
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'...
};
i błąd, że mam coraz podczas kompilacji z GCC jest:
invalid parameter type 'void' in declaration template<class Type, class Return, class Parameter, Return (Type::* Pointer)(Parameter)const>
w pierwszym wierszu struct sMemberMethodChecker
. Jestem całkiem pewien, że nie brakuje mi słów, ale nie rozumiem, dlaczego dostaję błąd i nie rozumiem błędu.
Wiem, że MSVC jest luźny ze standardem podczas GCC jest zgodny ze standardem całkiem dobrze, więc zastanawiam się, czy problem leży w bok MSVC który pozwala kodu głupie!
Oto pytania:
- Dlaczego otrzymuję błąd
invalid parameter type 'void'
wstruct sMemberMethodChecker
?. - Dlaczego kod jest poprawny w MSVC, ale jest nieprawidłowy w GCC ?.
- Czy ten kod jest niestandardowy ?.
- Czy sztuczka SFINAE nie zawiera C++ 11?
Czy "const void * const" jest dozwolone? Mówisz kompilatorowi, że masz obiekt typu "const void". Ale pustki nie mogą być modyfikowane tak czy inaczej AFAIK? Co się stanie, jeśli spróbujesz 'void * const'? – RedX
Dobre pytanie. Wydaje się, że GCC nie akceptuje 'szablon < TypeName typ, TypeName powrót, TypeName parametr Return (Typ :: *) (void **' ** ') > struct sMemberMethod {};' jako parametr . Podczas gdy MSVC jest o tym liberalny. – iammilind
Uważam, że iammilind ma rację. W przeciwieństwie do C, C++ nie zezwala na 'void' na liście argumentów funkcji. Dzieje się tak, ponieważ w C 'f()' jest funkcją bez prototypu (= parametry nieokreślone), natomiast w C++ 'f()' jest funkcją bez żadnych argumentów. – Angew