Автоматизировать вызов метода C++

Я работаю над приложением C++11. Там у меня есть метод, который будет вызываться много раз (1000). Этот метод принимает в качестве параметров строку и указатель на функцию.

Дело в том, что указатель на функцию будет принимать разные типы аргументов, иногда int, иногда std:string и так далее.

Чтобы избежать 1000 разных обращений к моему методу, у меня есть возможность построить список std:: пар со строкой и указателем на функции и выполнить итерацию по нему для вызова моего метода.

Но я не нашел чистого способа добиться этого.

пример:

// This is the method I want to call, 
// T is function pointer, I have several versions for
// different data types, e.g here bool version
template <class T>
void myMethod(const std::string& strArg,
              void (T::*setter) (const bool)) const

Предыдущий метод будет вызываться 1000 раз с разными аргументами: каждая строка соответствует уникальному указателю функции.

Теперь я называю это 1000 раз как:

myMethod(str1, pFunction1);
myMethod(str2, pFunction2);
myMethod(str3, pFunction3);
...
myMethod(str1000, pFunction1000);

Я хотел бы сначала создать список, заполненный мной вручную:

std::list<std::pair<str, functionPointer>>

Затем я бы повторил вызов моего метода для каждого члена в списке

Есть идеи, пожалуйста?

Спасибо и всего наилучшего

2 ответа

Решение

Да, вы можете иметь коллекцию таких пар.

std::vector<std::pair<std::string, void (SomeClass::*) (const bool)>> myMethodArgs 
{
    { str1, pFunction1 },
    { str2, pFunction2 },
    ...
    { str1000, pFunction1000 },
};

А потом позвонить им всем

for (auto & pair : myMethodArgs)
{
     myMethod(pair.first, pair.second); // deduces myMethod<SomeClass>
}

Но, похоже, у вас есть разные типы для многих из этих вызовов. Вы могли бы вместо этого иметь коллекцию std::function<void()>s сделаны из лямбд, с каждым отдельным экземпляром myMethod

std::vector<std::function<void()>> myMethodCalls
{
    []{ myMethod(str1, &Class1::method); },
    []{ myMethod(str2, &Class2::other_method); },
    ...
    []{ myMethod(str1000, &Class1000::final_method); },
};

for (auto & call : myMethodCalls)
{
    call();
}

Я хотел бы, чтобы вы дошли до того момента, когда захотите вызвать свою функцию позже!

Предположим, что мы можем написать код, который вам нравится (псевдокод):

std::list<std::pair<str, PointerToFunctionWithAnySignature >> ptrList;

теперь вы пополняете список

ptrList.add( "bla", Do1 );
ptrList.add( "blub", Do2 );

и подпись функций выглядит так:

void Do1(int);
void Do2(float, std::string& );

Теперь вы хотите перебрать список:

for ( auto& el: ptrList )
{
    // here we want to call the function:
    el.second( ???????? );
}

Это вопрос! Если у вас разные подписи: как вы хотите узнать, какой параметр вы должны заполнить, какую позицию в этом вызове.

В результате, даже если вы можете хранить указатели на функции с разными сигнатурами, это не имеет смысла, потому что вы не можете их вызывать!

Если вы уже знаете параметры для последующего вызова, вы можете использовать lambda functions хранить функцию и параметры в виде единого объекта и делать его доступным с уникальной подписью. Вы также можете использовать std::bind для этого, но лямбда предпочтительнее, проще в обращении и проще для чтения.

Другие вопросы по тегам