1

背景:我正在使用委托技术来抽象访问任意对象方法,但我在链接器方面存在一些问题。考虑以下课程,ContextNode无法解析模板委托中的重载类方法

template <class ObjectType, class GetType, class SetType> 
class ContextNode: public ContextNodeBase { 
    public: 
    ContextNode(ObjectType* target, 
       GetType (ObjectType::*getter)(void), 
       void (ObjectType::*setter)(const SetType& ref) 
    ): _target(target), _getter(getter), _setter(setter) { } 

    virtual ~ContextNode(void) { } 

    virtual void r(Datum& value) { 
     value = (_target->*_getter)(); 
     return; 
    } 

    virtual void w(const Datum& value) { 
     (_target->*_setter)(value); 
     return; 
    } 

    private: 
    ObjectType* _target; 
    GetType (ObjectType::*_getter)(void); 
    void (ObjectType::*_setter)(const SetType& ref); 
}; 

Datum的执行是无关紧要的。也考虑微不足道的类Thing

class Thing { 
    public: 
    Thing(void); 
    ~Thing(void); 

    int getValue(void)   { return _value; } 
    void setValue(const int& x) { _value = x; } 
    private: 
    int _value; 
}; 

问题:我可以构建的ContextNode实例,像这样。

Thing* thing = new Thing(); 
ContextNode<Thing,int,int>* cn = new ContextNode<Thing,int,int>(thing, &Thing::getValue, &Thing::setValue); 

这适用于我的需要。我遇到问题,但重载的方法。假设我写了:

class Thing { 
    public: 
    Thing(void); 
    ~Thing(void); 

    int value(void)   { return _value; } 
    void value(const int& x) { _value = x; } 
    private: 
    int _value; 
}; 

Thing* thing = new Thing(); 
ContextNode<Thing,int,int>* cn = new ContextNode<Thing,int,int>(thing, &Thing::value, &Thing::value); 

这未能链接。我相信这个问题是链接器仅尝试基于名称的解析,因此我看到了<unresolved overloaded function type>错误。

我的问题:是否有一些语法糖来显式指定我指的几个重载方法中的哪一个?我无法想象这样一个愚蠢的怪癖会打破这样一个优雅的解决方案。我在网上找不到任何东西,也没有找到C++常见问题解答,也没有关于这个话题的SO。

什么是修复程序,或者我洗过?

回答

2

您可以使用强制转换为消除歧义的重载函数名称:

(int (Thing::*)(void))(&Thing::value) 
(void (Thing::*)(const int&))(&Thing::value) 
+0

好主意,但是'错误:没有上下文类型信息的重载函数的地址' – 2010-10-16 02:09:17

+0

哦,具体来说,这个错误来自于getter的转换,而不是setter。 – 2010-10-16 02:28:25

+0

Bah - 我的错。我有一些常量声明是错误的。谢谢! – 2010-10-16 02:34:58

1

这也可能是能够提供一种选择一个或另一个重载的实用功能。

//enjoy the syntax: function accepting and returning a pointer to member function 
template <class Object, class T> 
T (Object::*as_getter(T (Object::*f)()))() 
{ 
    return f; 
} 

template <class Object, class T> 
void (Object::*as_setter(void (Object::*f)(T)))(T) 
{ 
    return f; 
} 

class Thing { 
    public: 
    Thing(void); 
    ~Thing(void); 

    int value(void)   { return _value; } 
    void value(const int& x) { _value = x; } 
    private: 
    int _value; 
}; 

template <class F> 
void foo(F f) 
{} 

int main() 
{ 
    foo(as_getter(&Thing::value)); //selects methods of kind X Y::zzz() 
    foo(as_setter(&Thing::value)); //selects methods of kind void Y::zzz(X) 
} 

然而,通常干将是const的方法,所以as_getter也可能要面对这一切。另外,如果可能的话,避免不必要的重载,特别是如果你想使用函数指针。国际海事组织,一个吸气者和一个接二连三做了足够不同的事情,值得一个不同的名字。

+0

哦,人 - 好主意!如果我将它们内联,一旦模板类型得到解决,编译器应该基本上能够优化调用权,实际上不会产生额外的运行时间开销。真棒抽象! +1! – 2010-10-16 13:14:06