无法解析模板委托中的重载类方法
背景:我正在使用委托技术来抽象访问任意对象方法,但我在链接器方面存在一些问题。考虑以下课程,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。
什么是修复程序,或者我洗过?
您可以使用强制转换为消除歧义的重载函数名称:
(int (Thing::*)(void))(&Thing::value)
(void (Thing::*)(const int&))(&Thing::value)
这也可能是能够提供一种选择一个或另一个重载的实用功能。
//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
也可能要面对这一切。另外,如果可能的话,避免不必要的重载,特别是如果你想使用函数指针。国际海事组织,一个吸气者和一个接二连三做了足够不同的事情,值得一个不同的名字。
哦,人 - 好主意!如果我将它们内联,一旦模板类型得到解决,编译器应该基本上能够优化调用权,实际上不会产生额外的运行时间开销。真棒抽象! +1! – 2010-10-16 13:14:06
好主意,但是'错误:没有上下文类型信息的重载函数的地址' – 2010-10-16 02:09:17
哦,具体来说,这个错误来自于getter的转换,而不是setter。 – 2010-10-16 02:28:25
Bah - 我的错。我有一些常量声明是错误的。谢谢! – 2010-10-16 02:34:58