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

它不编译的原因很简单,就是有几个不同的重载函数,它不知道你指的是哪一个。当然,考虑到 specialization ,其中只有一个 (void set(int,int)) 会实际编译Helper<test,INT_2>。但是,这还不足以让编译器继续运行。

使其编译的一种方法是显式&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 回答