Line data Source code
1 : #pragma once
2 : #include <tuple>
3 : #include <utility>
4 :
5 : namespace chip {
6 :
7 : namespace detail {
8 : template <typename T>
9 : struct SplitLambdaCallerImpl;
10 :
11 : // Detail -- Specialization to extract argument and return types from the callable type.
12 : template <class TReturn, class TCallable, class... TArgs>
13 : struct SplitLambdaCallerImpl<TReturn (TCallable::*)(TArgs...) const>
14 : {
15 :
16 : // This call function knows the arguments and provides the signature required for the C-like callbacks
17 6 : static TReturn Call(TArgs... args, void * context)
18 : {
19 6 : return (*static_cast<TCallable *>(context))(std::forward<TArgs>(args)...);
20 : }
21 : };
22 : } // namespace detail
23 :
24 : /// @brief Helper Object to use Lambdas through C-Like APIs where context is split from the callback.
25 : /// This incurs no runtime code execution; just keeps everything typesafe.
26 : /// @tparam TCallable
27 : /// @example
28 : /// /* FunctionAPI */
29 : /// int api_function(void (*callback) (int api_value, void * context), void * context );
30 : ///
31 : /// int local_function()
32 : /// {
33 : /// int local_api_value = -1;
34 : /// int other_local_variable = 7;
35 : ///
36 : /// SplitLambda on_api_update_my_vars = [&](int value){
37 : /// local_api_value = value;
38 : /// other_local_variable = value +3;
39 : /// };
40 : ///
41 : /// /*Call API */
42 : /// return api_function(on_api_update_my_vars.Caller(), on_api_update_my_vars.Context());
43 : /// }
44 : template <class TCallable>
45 : struct SplitLambda : detail::SplitLambdaCallerImpl<decltype(&TCallable::operator())>
46 : {
47 : TCallable callable;
48 :
49 12 : SplitLambda(TCallable callable_) : callable(callable_) {}
50 : SplitLambda(SplitLambda &) = delete; // Cannot be copied
51 : SplitLambda(SplitLambda &&) = delete; // Cannot be moved
52 :
53 12 : inline void * Context() { return static_cast<void *>(&callable); }
54 12 : inline auto Caller() { return &this->Call; }
55 : };
56 :
57 : template <class TCallable>
58 : SplitLambda(TCallable callable_) -> SplitLambda<TCallable>;
59 :
60 : } // namespace chip
|