diff --git a/include/cppkafka/utils/consumer_dispatcher.h b/include/cppkafka/utils/consumer_dispatcher.h index 05e5c49..0b1925d 100644 --- a/include/cppkafka/utils/consumer_dispatcher.h +++ b/include/cppkafka/utils/consumer_dispatcher.h @@ -102,6 +102,12 @@ public: */ void stop(); private: + // Define the types we need for each type of callback + using OnMessageArgs = std::tuple; + using OnErrorArgs = std::tuple; + using OnEofArgs = std::tuple; + using OnTimeoutArgs = std::tuple; + static void handle_error(Error error); static void handle_eof(EndOfFile, const TopicPartition& topic_partition); static void handle_timeout(Timeout); @@ -189,19 +195,45 @@ private: return find_functor(functors...); } + // Check that a given functor matches at least one of the expected signatures + template + void check_callback_matches(const Functor& functor) { + static_assert( + !std::is_same::type>::value || + !std::is_same::type>::value || + !std::is_same::type>::value || + !std::is_same::type>::value, + "Callback doesn't match any of the expected signatures" + ); + } + + // Base case for recursion + void check_callbacks_match() { + + } + + // Check that all given functors match at least one of the expected signatures + template + void check_callbacks_match(const Functor& functor, const Functors&... functors) { + check_callback_matches(functor); + check_callbacks_match(functors...); + } + Consumer& consumer_; bool running_; }; template void ConsumerDispatcher::run(const Args&... args) { - // Define the types we need for each type of callback - using OnMessageArgs = std::tuple; - using OnErrorArgs = std::tuple; - using OnEofArgs = std::tuple; - using OnTimeoutArgs = std::tuple; - using self = ConsumerDispatcher; + + // Make sure all callbacks match one of the signatures. Otherwise users could provide + // bogus callbacks that would never be executed + check_callbacks_match(args...); // This one is required const auto& on_message = find_callable_functor(args...);