Невозможно разрешить перегруженные методы класса в шаблоне делегата. - PullRequest
1 голос
/ 16 октября 2010

Справочная информация: Я использую технику делегирования для абстрагирования доступа к произвольным объектным методам, но у меня возникают некоторые проблемы, связанные с компоновщиком.Рассмотрим следующий класс: 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 ++ FAQ, ни прямо здесь, в SO по этой теме.

В чём дело, или я заскочил?

Ответы [ 2 ]

2 голосов
/ 16 октября 2010

Вы можете использовать приведение для устранения неоднозначности имени перегруженной функции:

(int (Thing::*)(void))(&Thing::value)
(void (Thing::*)(const int&))(&Thing::value)
1 голос
/ 16 октября 2010

Также может быть возможно предоставить служебные функции, которые выбирают ту или иную из перегрузок.

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

Однако методы получения обычно являются константными методами, поэтому as_getter может также захотеть иметь дело с этим.

Также, если возможно, избегайте ненужной перегрузки, особенно если вы хотите работать с указателями функций. ИМО, геттер и сеттер делают достаточно разные вещи, чтобы заслужить другое имя.

...