Рефакторинг, где уникальные функции имеют разные аргументы - PullRequest
0 голосов
/ 08 января 2019

У меня есть класс (выступающий в качестве оболочки над библиотекой) с функциями-членами, которые следуют этому шаблону:

MyObject& MyObject::ObjectFunction(int arg1, std::string arg2)
{
    LibraryObject destination_object;
    libraryFunction(destination_object, arg1, arg2);
    setProp(destination_object);
    ~destination_object;
    return *this;
}

Я хотел бы реорганизовать это так, чтобы повторяющиеся шаги (создание целевого объекта, установка свойства, уничтожение целевого объекта, обратный адрес) могли быть перемещены в собственную функцию, в идеале что-то вроде этого:

MyObject& MyObject::genericFunction (uniqueLibraryFunction(Args)) 
{
    LibraryObject destination_object;
    uniqueLibraryFunction(Args);
    setProp(destination_object);
    ~destination_object;
    return *this;        
}

void libraryFunction1(int arg1, std::string arg2) 
{
    genericFunction(libraryFunction1(arg1, arg2));
}

void libraryFunction2(double arg1, int arg2) 
{
    genericFunction(libraryFunction2(arg1, arg2));
}

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

Мой код класса следующий:

class MyObject 
{
    private:
        LibraryObject prop;
    public:
        getProp();
        setProp(int prop);
}

1 Ответ

0 голосов
/ 08 января 2019

Если я правильно понимаю вопрос, то это должно быть выполнимо с лямбдой:

template <class F>
MyObject& MyObject::genericFunction(F f) 
{
    LibraryObject destination_object;
    f(destination_object);
    setProp(destination_object);
    return *this;        
}

void MyObject::libraryFunction1(int arg1, std::string arg2) 
{
    genericFunction([=](LibraryObject &o) { libraryFunction1(o, arg1, arg2); });
}

void libraryFunction2(double arg1, int arg2) 
{
    genericFunction([=](LibraryObject &o) { libraryFunction2(o, arg1, arg2); });
}

В качестве альтернативы std::bind будет выполнять ту же работу:

void MyObject::libraryFunction1(int arg1, std::string arg2) 
{
  genericFunction(std::bind(libraryFunction1, std::placeholders::_1, arg1, arg2));
}

Шаблон не должен быть проблемой, так как, если он закрытый, его можно легко реализовать только в исходном файле, где находятся все обращения к нему. Однако, если по какой-либо причине это не подходит вам, вы можете использовать std::function<void(LibraryObject&)> вместо F.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...