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