如何查找某个类中是否存在特定原型的方法?

时间:2012-11-20 07:52:10

标签: c++ templates visual-c++ gcc sfinae

我正在使用一些SFINAE功能;目前在必须在Linux和Windows中运行的应用程序的一部分中;编译器选择是针对Windows应用程序的MSVC(Visual Studio 2010 10.0)和针对Linux应用程序的GCC 4.4.5。

我必须检查某个给定对象是否提供了一些函数来执行自定义序列化并调用此函数,或者在未提供自定义序列化方法时执行简单的memcpysizeof(Object)

问题是一段代码在MSVC中编译时没有警告也没有错误,但在使用GCC进行编译时,代码如下:

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编译时遇到的错误是:

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

struct sMemberMethodChecker的第一行。我很确定我不会错过typename或错误的单词,但我不明白为什么我收到错误并且不理解错误。

我知道MSVC标准不严格,而GCC很好地符合标准,所以我想知道问题是否存在于允许愚蠢代码的MSVC方面!

以下是问题:

  • 为什么我在invalid parameter type 'void'
  • 中收到struct sMemberMethodChecker错误
  • 为什么代码在MSVC中有效但在GCC中无效?。
  • 此代码是否非标准?。
  • SFINAE技巧是否不包括C ++ 11?

1 个答案:

答案 0 :(得分:2)

  

为什么我收到无效的参数类型&#39; void&#39;结构中的错误   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++