3

関係のないメンバーを受け入れる特殊化を(enable_ifを介して)削除することにより、メンバーの「タイプ」に基づいて、オーバーロードされたメンバーの中から適切なメンバーへのポインターを自動的に選択したいと思います。

私は次のコードを持っています:

class test;

enum Type
{
    INT_1,
    FLOAT_1,
    UINT_1,
    CHAR_1,
    BOOL_1,
    INT_2,
    FLOAT_2,
    UINT_2,
    CHAR_2,
    BOOL_2
};
template<typename T, Type Et, typename func> struct SetterOk                            { static const bool value = false; };
template<typename T> struct SetterOk<T,INT_1,void (T::*)(int)>                          { static const bool value = true; };
template<typename T> struct SetterOk<T,FLOAT_1,void (T::*)(float)>                      { static const bool value = true; };
template<typename T> struct SetterOk<T,UINT_1,void (T::*)(unsigned int)>                { static const bool value = true; };
template<typename T> struct SetterOk<T,CHAR_1,void (T::*)(char)>                        { static const bool value = true; };
template<typename T> struct SetterOk<T,BOOL_1,void (T::*)(bool)>                        { static const bool value = true; };
template<typename T> struct SetterOk<T,INT_2,void (T::*)(int,int)>                      { static const bool value = true; };
template<typename T> struct SetterOk<T,FLOAT_2,void (T::*)(float,float)>                { static const bool value = true; };
template<typename T> struct SetterOk<T,UINT_2,void (T::*)(unsigned int, unsigned int)>  { static const bool value = true; };
template<typename T> struct SetterOk<T,CHAR_2,void (T::*)(char,char)>                   { static const bool value = true; };
template<typename T> struct SetterOk<T,BOOL_2,void (T::*)(bool,bool)>                   { static const bool value = true; };

template <bool, class T = void> struct enable_if {};
template <class T> struct enable_if<true, T> { typedef T type; };


template<typename T, Type Et>
struct Helper
{
    template<typename U>
    static void func(U method, typename enable_if<SetterOk<T,Et,U>::value>::type* dummy = 0)
    {
    }
};

class test
{
    public:
        void init()
        {
            Helper<test,INT_2>::func(&test::set);
        }

        void set2(int);
        void set(int);
        void set(int,int);
        void set(float,float);
};

int main()
{
    test t;
    t.init();
    return 0;
}

私はそれが可能なすべての中から正しい機能を選択することを期待しています。問題は、コンパイラが「関数の引数があいまいなため、テンプレートの引数を推測できない」と言っていることです。

enable_ifの使用方法がわからないようです。その場合、コンパイラは、指定された関数が正しいタイプである場合にのみ特殊化を許可するためです...

(可能であれば)C ++ 03ソリュ​​ーションが必要であることに注意してください。コードは、いくつかの古いコンパイラでコンパイルする必要があります。

前もって感謝します

4

2 に答える 2

1

オーバーロードされた関数は、曖昧さを解消せずに参照することはできません(つまりstatic_cast、正しい型に変換する)。関数の引数の型をインスタンス化Helper::funcすると、曖昧さを解消せずにそれを知ることはできません。

于 2012-03-15T16:33:10.467 に答える
1

コンパイルされない理由は、非常に単純に、いくつかの異なるオーバーロードされた関数があり、どれを意味するのかわからないためです。確かに、特殊化が与えられた場合、これらの1つ(void set(int、int))のみが実際にコンパイルされますHelper<test,INT_2>。ただし、これはコンパイラーが続行するには十分ではありません。

これをコンパイルする1つの方法は&test::set、適切なタイプに明示的にキャストすることです。

Helper<test,INT_2>::func(static_cast<void (test::*)(int,int)>(&test::set));

別の方法は、明示的なテンプレートの特殊化を使用することです。

Helper<test,INT_2>::func<void (test::*)(int,int)>((&test::set));

いずれにせよ、参照しようとしている集合関数のどれかをコンパイラーに知らせる必要があります。

編集:

私が理解しているように、Typeの使用から、どの関数型を使用すべきかを推測できるようにしたいと考えています。次の代替手段はこれを実現します。

template<typename T, Type Et> struct SetterOK{};
template<typename T> struct SetterOK<T,INT_1> {typedef void (T::*setter_type)(int);};
template<typename T> struct SetterOK<T,FLOAT_1> {typedef void (T::*setter_type) (float);};
// ...
template<typename T> struct SetterOK<T,INT_2> {typedef void (T::*setter_type)(int,int);};
// ....

template<typename T, Type Et>
struct Helper
{
  template<typename U>
  static void func(U method)
  {
  }
};

class test
{
public:
  void init()
  {
    Helper<test,INT_2>::func<SetterOK<test,INT_2>::setter_type >(&test::set);
  }

  void set2(int);
  void set(int);
  void set(int,int);
  void set(float,float);
};

int main()
{
  test t;
  t.init();
  return 0;
}

追加の編集:

思いついたばかりです。UがSetterOK::setter_typeである、あなたが行ったこの特別なケースでは、funcのテンプレート引数を完全に削除することで、物事をさらに単純化することができます。

static void func(typename SetterOK<T,Et>::setter_type method)
{
}

これにより、initメソッドがより簡単になります。

void init()
{
  Helper<test,INT_2>::func(&test::set);
}
于 2012-03-15T17:23:23.687 に答える