Мне нужна структура данных, которая каждой строке будет ставить в соответствие некоторую callback-функцию. Эта структура будет инициализироваться извне класса с помощью лямбд. Какую структуру данных лучше использовать, если сигнатуры функций могут быть разными?
Нужно такое поведение:
map["gui_ok_button"] = [&](){
data.apply();
};
map["gui_close_button"] = [&](int close_code){
data.close(close_code);
};
Новые возможности Си++17 вам помогут. Могу предложить реализация на std::variant
:
#include <map>
#include <string>
#include <functional>
#include <variant>
// здесь должны быть перечислены варианты
// всех сигнатур
using Callback = std::variant
<
std::function<void(void)>
, std::function<void(int)>
, std::function<void(const std::string&)>
>;
using CallbackMap = std::map<std::string, Callback>;
Далее главная идея решения, функция вызова:
// Эта перегрузка нужна для обработки неверных вызовов
// статическая проверка пока не приходит на ум.
template<typename F, typename ...A>
void DoCall(F&&, A&&...)
{
throw std::bad_variant_access();
}
// Нужно для каждой варианта сигнатуры определить перегрузку для проброски
// аргументов. Выглядит коряво, тут можно автоматизировать.
void DoCall(std::function<void(void)> & f)
{
f();
}
void DoCall(std::function<void(int)> & f, int arg)
{
f(arg);
}
void DoCall(std::function<void(const std::string&)> & f, const std::string & arg)
{
f(arg);
}
// Собственно вызов калбека
template<typename ...A>
void Dispatch(const Callback & callback, A&& ...args)
{
// здесь лямбда нужна чтобы захватить args и передать в DoCall,
// все из-за того что std::visit не предусматривает проброс
// аргументов в посетителя (здесь в нашу лямбду)
std::visit
(
[&args...](auto && func) -> void
{
DoCall(func, std::forward<A>(args)...);
}
, callback
);
}
Использовать это вот так как-то:
void TestCallbackMap()
{
auto cm = CallbackMap();
cm["foo"] = [](void) -> void
{
std::cout << "call: foo" << std::endl;
};
cm["bar"] = [](int arg) -> void
{
std::cout << "call: bar " << arg << std::endl;
};
cm["baz"] = [](const std::string & msg) -> void
{
std::cout << "call: baz " << msg << std::endl;
};
Dispatch(cm["baz"], std::string("hello world"));
}
Виртуальный выделенный сервер (VDS) становится отличным выбором
Где subset1 и subset2 - это вектора подмножеств первой и второй половины множества соответственно
Начал копать библиотеку уроков по тому как работает OpenGL и не могу разобраться с одним методомСсылка на курс: https://github
Интересует, как можно получить доступ к элементу map'ы с индексом iНо! К примеру, при перебирании map'ы при помощи итерататора она отсортирована...