5

私はいくつかのSFINAE機能を使用しています。現在、LinuxおよびWindowsで実行する必要があるアプリケーションの一部にあります。コンパイラの選択肢は、Windowsアプリケーションの場合はMSVC(Visual Studio 2010 10.0)、Linuxアプリケーションの場合はGCC4.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'...
    };

そして、GCCでコンパイルしているときに発生するエラーは次のとおりです。

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

の最初の行にありstruct sMemberMethodCheckerます。sを見逃したり、単語を置き忘れたりしていないことは確かですtypenameが、なぜエラーが発生するのか理解できず、エラーも理解できません。

私はMSVCが標準に緩いことを知っていますが、GCCは標準にかなりよく準拠しているので、問題は愚かなコードを許可するMSVC側にあるのだろうかと思います!

質問は次のとおりです。

  • なぜinvalid parameter type 'void'エラーが発生するのstruct sMemberMethodCheckerですか?
  • コードがMSVCでは有効であるのに、GCCでは無効であるのはなぜですか。
  • このコードは非標準ですか?
  • SFINAEのトリックはC++11専用ですか?
4

1 に答える 1

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));
};

HasMethod<ClassName, ClassMethodType>::value特定のタイプのメンバーメソッドがその中に存在するかどうかの答えを提供します。
現在のところ、ユーザー指定のタイプを使用したメソッドの命名HasMethod<>専用です。ただし、上記のコードのマクロを作成して、関数名を構成可能にすることはできます。 size

これはg++で動作するデモです

于 2012-11-20T08:45:13.070 に答える