I'm working with some SFINAE features; currently in a portion of an application that must run in Linux and Windows; the compiler choices are MSVC (Visual Studio 2010 10.0) for Windows applications and GCC 4.4.5 for the Linux ones.
I must check if some given object provides some functions to perform a custom serialization and call this functions, or do a simple memcpy
and sizeof(Object)
while the custom serialization methods are not provided.
The problem is that a piece of code compile without warnings nor errors in MSVC but while compiling with GCC, the code is the following:
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'...
};
And the error that I'm getting while compiling with GCC is:
invalid parameter type 'void' in declaration template<class Type, class Return, class Parameter, Return (Type::* Pointer)(Parameter)const>
in the first line of the struct sMemberMethodChecker
. I'm quite sure that I'm don't missing typename
s nor misplacing words but I don't understand why I'm getting the error and doesn't understand the error.
I know that the MSVC is lax with standard while GCC conforms the standard pretty well so I'm wondering if the problem lies into the MSVC side that allows silly code!
Here are the questions:
- Why am I getting the
invalid parameter type 'void'
error in thestruct sMemberMethodChecker
?. - Why the code is valid in MSVC but invalid in GCC?.
- Is this code non-standard?.
- Is the SFINAE trickery exclusive of C++11?
I believe that MSVC is being helpful however GCC is being stringent in this particular code. As it's somehow not allowing
Return (Type::*)(void)
. However one need to dig it more to know the exact reason.Can't say until it doesn't compile. And searching standard for the features like SFINAE is not everyone's cup of tea.
Not at all. SFINAE existed before C++11.
Here is the simplified way of what you want to do:
HasMethod<ClassName, ClassMethodType>::value
gives you the answer if a certain type member method exists inside it or not.As of now
HasMethod<>
is exclusive to the method namingsize
with user provided type. But you can create a macro for above code and make the function name configurable.Here is a working demo with g++.