Answer the question
In order to leave comments, you need to log in
One signature and multiple return types: how to defeat "ambiguity"?
There is a spherical code in a vacuum:
enum class Event {
CREATE, TERMINATE, TIMEOUT, PARTYTIME
};
static std::map<Event, std::function<void()>> callbackMap {
{ Event::CREATE, []{ std::cout << "CREATE\n"; } },
{ Event::TERMINATE, []{ std::cout << "TERMINATE\n"; } },
{ Event::TIMEOUT, []{ std::cout << "TIMEOUT\n"; } },
{ Event::PARTYTIME, []{ std::cout << "PARTYTIME\n"; } },
};
struct App {
struct Callback {
using Create = int(*)(void *);
using Terminate = void(*)(void *);
using Timeout = void(*)(void *); // идентичен с Terminate
using Partytime = const char *(*)(int, void *);
};
template <Event TEvent>
static Callback::Create getCallback() {
return [](void *) { callbackMap[TEvent](); return 42; };
}
};
// костыльная функция, роль которой в рельном коде выполняет ОС
template <typename T>
void caller(T callback) {
callback(nullptr);
}
int main() {
auto create = App::getCallback<Event::CREATE>();
// ОС дергает колбэк
caller(create);
}
Answer the question
In order to leave comments, you need to log in
This is how it turned out...
enum class Event {
CREATE, TERMINATE, TIMEOUT, PARTYTIME
};
static std::map<Event, std::function<void()>> callbackMap {
{ Event::CREATE, []{ std::cout << "CREATE\n"; } },
{ Event::TERMINATE, []{ std::cout << "TERMINATE\n"; } },
{ Event::TIMEOUT, []{ std::cout << "TIMEOUT\n"; } },
{ Event::PARTYTIME, []{ std::cout << "PARTYTIME\n"; } },
};
struct App {
struct Callback {
using Create = int(*)(void *);
using Terminate = void(*)(void *);
using Timeout = void(*)(void *); // идентичен с Terminate
using Partytime = const char *(*)(int, void *);
};
template <typename TCallback, Event TEvent>
static TCallback getCallback();
};
template <>
App::Callback::Create App::getCallback<App::Callback::Create, Event::CREATE>() {
return [](void *) { callbackMap[Event::CREATE](); return 42; };
}
template <>
App::Callback::Terminate App::getCallback <App::Callback::Terminate, Event::TERMINATE>() {
return [](void *) { callbackMap[Event::TERMINATE](); };
}
template <>
App::Callback::Timeout App::getCallback <App::Callback::Timeout, Event::TIMEOUT>() {
return [](void *) { callbackMap[Event::TIMEOUT](); };
}
template <>
App::Callback::Partytime App::getCallback <App::Callback::Partytime, Event::PARTYTIME>() {
return [](int, void *) -> const char * { callbackMap[Event::PARTYTIME](); return nullptr; };
}
// костыльная функция, роль которой в реальном коде выполняет ОС
template <typename T>
void caller(T callback) {
callback(nullptr);
}
template <>
void caller(App::Callback::Partytime callback) {
callback(0, nullptr);
}
int main() {
auto create = App::getCallback<App::Callback::Create, Event::CREATE>();
auto terminate = App::getCallback<App::Callback::Terminate, Event::TERMINATE>();
auto timeout = App::getCallback<App::Callback::Timeout, Event::TIMEOUT>();
auto partytime = App::getCallback<App::Callback::Partytime, Event::PARTYTIME>();
// ОС дергает колбэки
caller(create);
caller(terminate);
caller(timeout);
caller(partytime);
}
...
template <typename TCallback>
static TCallback getCallback();
template <typename TCallback, Event TEvent>
static TCallback getCallback();
...
auto create = App::getCallback<App::Callback::Create>();
auto terminate = App::getCallback<App::Callback::Terminate, Event::TERMINATE>();
auto timeout = App::getCallback<App::Callback::Timeout, Event::TIMEOUT>();
auto partytime = App::getCallback<App::Callback::Partytime>();
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question