J
J
johnslowpoke2016-08-14 01:19:16
C++ / C#
johnslowpoke, 2016-08-14 01:19:16

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);

}

How to implement getCallback for other events? Perhaps a bit of boilerplate magic is required?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
J
johnslowpoke, 2016-08-14
@johnslowpoke

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);

}

Due to the overload of the code, the meaning of the whole idea is lost, then it’s easier without lambdas and blackjack ...
UPD: a less loaded option, but you have to keep in mind the special calling rules for terminate and timeout
...
  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>();

I don't even know which is worse :/

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question