Автоматизировать вызов метода 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 для этого, но лямбда предпочтительнее, проще в обращении и проще для чтения.