我希望通过删除接受不关心成员的特殊化(通过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解决方案(如果可能的话) - 我的代码必须在一些旧的编译器上编译。
提前致谢
答案 0 :(得分:1)
如果没有消除歧义,你永远不能引用重载函数(意味着:static_cast
将其设置为正确的类型)。实例化Helper::func
时,如果没有消除歧义,就无法知道函数参数的类型。
答案 1 :(得分:1)
它不编译的原因很简单,有几个不同的重载函数,它不知道你的意思。当然,给定专门化Helper<test,INT_2>
,实际上只会编译其中一个(void set(int,int))。但是,这还不足以使编译器继续运行。
将此进行编译的一种方法是将&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);
}