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

Pap*_*ter 5 c++ gcc templates sfinae visual-c++

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

我必须检查某个给定对象是否提供了一些函数来执行自定义序列化并调用此函数,或者执行一个简单的操作memcpy,sizeof(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'...
    };
Run Code Online (Sandbox Code Playgroud)

我在使用GCC编译时遇到的错误是:

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

在第一行struct sMemberMethodChecker.我很确定我不会丢失typenames或者错误的单词,但我不明白为什么我收到错误并且不理解错误.

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

以下是问题:

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

iam*_*ind 2

为什么我在 sMemberMethodChecker 结构中收到无效参数类型“void”错误?

为什么代码在 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));
};
Run Code Online (Sandbox Code Playgroud)

HasMethod<ClassName, ClassMethodType>::value给你答案是否存在某种类型的成员方法。
到目前为止,HasMethod<>仅限于使用用户提供的类型命名的方法。 size但是您可以为上面的代码创建一个宏并使函数名称可配置

这是一个使用 g++ 的工作演示