1 //  Copyright (c) 2017 Antoine TRAN TAN
2 //
3 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
4 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 /// \file hpx/runtime/actions/make_action.hpp
7 
8 #ifndef HPX_RUNTIME_ACTIONS_LAMBDA_TO_ACTION_HPP
9 #define HPX_RUNTIME_ACTIONS_LAMBDA_TO_ACTION_HPP
10 
11 #include <hpx/include/plain_actions.hpp>
12 #include <string>
13 #include <type_traits>
14 #include <utility>
15 
16 namespace hpx { namespace actions
17 {
18     /// \cond NOINTERNAL
19 
20     ///////////////////////////////////////////////////////////////////////////
21     namespace detail
22     {
23         // Helpers to actionize a lambda
24 
25         template <typename ... T>
26         struct sequence
27         {};
28 
29         struct addr_add
30         {
31             template<class T>
32             friend typename std::remove_reference<T>::type *
operator +(addr_add,T && t)33             operator+(addr_add, T &&t)
34             {
35                 return &t;
36             }
37         };
38 
39 
40         template<typename F, typename ReturnType, typename... Args>
41         struct lambda_action
42           : basic_action<detail::plain_function, ReturnType(Args...),
43             lambda_action<F, ReturnType, Args...>>
44         {
45             typedef lambda_action derived_type;
46             typedef std::false_type direct_execution;
47             typedef void is_plain_action;
48 
get_action_namehpx::actions::detail::lambda_action49             static std::string get_action_name(naming::address::address_type /*lva*/)
50             {
51                 return "lambda action()";
52             }
53 
54             template <typename ...Ts>
invokehpx::actions::detail::lambda_action55             static ReturnType invoke(naming::address::address_type /*lva*/,
56                 naming::address::component_type comptype, Ts&&... vs)
57             {
58                  int * dummy = nullptr;
59                  return reinterpret_cast<const F&>(*dummy)( std::forward<Ts>(vs)... );
60             }
61         };
62 
63         template <typename F, typename T>
64         struct extract_lambda_action
65         {};
66 
67         // Specialization for lambdas
68         template <typename F, typename ClassType, typename ReturnType, typename... Args>
69         struct extract_lambda_action<F, ReturnType(ClassType::*)(Args...) const>
70         {
71             using type = lambda_action<F, ReturnType, Args...>;
72         };
73 
74         template <typename F>
75         struct action_from_lambda
76         {
77             using type =
78                 typename extract_lambda_action<F, decltype(&F::operator())>::type;
79         };
80 
81         struct action_maker
82         {
83             template<typename F>
84             HPX_CONSTEXPR typename hpx::actions::detail::action_from_lambda<F>::type
operator +=hpx::actions::detail::action_maker85             operator += (F*) const
86             {
87                 static_assert(
88                     //!std::is_assignable<F,F>::value &&
89                     std::is_empty<F>::value,
90                     "lambda_to_action() needs and only needs a lambda with empty " \
91                     "capture list");
92 
93                 return typename
94                     hpx::actions::detail::action_from_lambda<F>::type();
95             }
96         };
97     }
98 
99     template<typename F>
lambda_to_action(F && f)100     auto lambda_to_action(F&& f)
101     -> decltype( hpx::actions::detail::action_maker() += true
102         ? nullptr
103         : hpx::actions::detail::addr_add() +  f)
104     {
105         HPX_CONSTEXPR auto act =
106             hpx::actions::detail::action_maker() += true
107             ? nullptr
108             : hpx::actions::detail::addr_add() +  f;
109 
110         return act;
111     }
112 }}
113 
114 #endif /*HPX_RUNTIME_ACTIONS_LAMBDA_TO_ACTION_HPP*/
115