无法解析模板委托中重载的类方法

发布于 2024-09-28 09:05:58 字数 2041 浏览 8 评论 0原文

背景:我使用委托技术来抽象对任意对象方法的访问,但在链接器方面遇到了一些问题。考虑以下类,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);

这无法链接。我认为问题在于链接器仅尝试基于名称的解析,因此我看到 错误。

我的问题:是否有一些语法糖可以显式指定我所指的几个重载方法中的哪一个?我无法想象这样一个愚蠢的怪癖会破坏如此优雅的解决方案。我在网上、C++ 常见问题解答中都找不到任何关于该主题的信息。

有什么办法解决,还是我已经被淹了?

Background: I'm using a delegation technique to abstract access to arbitrary object methods, but I'm having some issues where the linker is concerned. Consider the following class, 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);
};

The implementation of Datum is irrelevant. Also consider the trivial class Thing.

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

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

The problem: I can construct instantiations of ContextNode like so.

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

This works well for my needs. I run into issues though, with overloaded methods. Assume I had written instead:

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);

This fails to link. The issue, I believe, is that the linker is attempting name-based resolution only, thus I see <unresolved overloaded function type> errors.

My question: is there some syntax sugar to explicitly specify to which of several overloaded methods I'm referring? I can't imagine that such a silly quirk would break such an elegant solution. I've been able to find nothing online, nor on the C++ FAQ, nor right here on SO regarding the topic.

What's the fix, or am I hosed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

揪着可爱 2024-10-05 09:05:58

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

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

You can use a cast to disambiguate an overloaded function name:

(int (Thing::*)(void))(&Thing::value)
(void (Thing::*)(const int&))(&Thing::value)
梦幻的味道 2024-10-05 09:05:58

还可以提供选择一个或另一个重载的实用函数。

//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)
}

然而,getter 通常是 const 方法,因此 as_getter 可能也想处理这个问题。

另外,如果可能的话,请避免不必要的重载,特别是如果您想使用函数指针。 IMO,getter 和 setter 做的事情完全不同,值得有不同的名称。

It might also be possible to provide utility functions that select one or another of the overloads.

//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)
}

However, getters normally are const methods, so as_getter might also want to deal with that.

Also, if possible, avoid needless overloading, particularly if you want to work with function pointers. IMO, a getter and a setter do sufficiently different things to deserve a different name.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文