2012-03-15 81 views
3

我想通过删除接受不关心成员的特殊化(通过enable_if),根据成员的“类型”自动选择正确的指向成员的指针。未被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

编译器只是简单地不知道哪个集合重载选择甚至开始实例化处理 – PlasmaHH 2012-03-15 16:33:45

+0

我想我已经找到了一个替代解决方案来解决你的问题。请检查我的答案。 – Agentlien 2012-03-15 17:39:31

回答

1

你永远不能指代一个重载函数没有消除歧义它(指:static_cast它荷兰国际集团为正确的类型)。当你实例化Helper::func时,函数参数的类型在不消除歧义的情况下是无法知道的。

+0

但编译器可以尝试专门为每个重载的'&Helper :: set'函数,然后选择匹配的(如果存在)。那么,为什么编译器不能像那样工作? 是否有解决方法? – Synxis 2012-03-15 16:46:03

+0

@Synxis问题甚至比'SetterOK'的实例更早出现,但是在'Helper'中,由于第二个参数的类型未知,无法实例化。我的错。没有真正的解决方法。重载函数在这些上下文中很难使用。 – pmr 2012-03-15 16:52:40

+0

不明白“第二个参数的类型是未知的”:它是INT_2,它是一个枚举值,如此完全已知,不是吗? – Synxis 2012-03-15 17:01:53

1

它不编译的原因很简单,就是有几个不同的重载函数,它不知道你指的是哪一个。当然,只有其中一个(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));

无论哪种方式,您都需要让编译器知道您尝试引用哪些函数。

编辑:

据我了解,你希望能够推断,从使用A型,功能类型应使用哪个的。以下替代实现这一点:

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

谢谢你的想法,但我已经使用这个。我问这个问题的原因是因为我有一个SetterOK,它的setter_type为'void(T :: *)(int)',我希望能够传递像'void(T :: *)(MyEnum )”。棘手的一点是我不知道'MyEnum'存在。但还有更多的:指向成员的指针可能有1,2,3或4个参数... 作为一个解决方案,我做了4个专门化,它们都需要一个函数'void(T :: *)(。 ...)(其中'...'是'U','U,U','U,U,U'或'U,U,U,U',仍然存在模糊调用的情况,但更少。 – Synxis 2012-03-15 18:37:13

相关问题