1 #ifndef _SIGC_ADAPTORS_HIDE_H_
2 #define _SIGC_ADAPTORS_HIDE_H_
4 #include <sigc++/adaptors/adaptor_trait.h>
5 #include <sigc++/tuple-utils/tuple_end.h>
6 #include <sigc++/tuple-utils/tuple_start.h>
10 /** @defgroup hide hide(), hide_return()
11 * sigc::hide() alters an arbitrary functor in that it adds a parameter
12 * whose value is ignored on invocation of the returned functor.
13 * Thus you can discard one argument of a signal.
15 * You may optionally specify the zero-based position of the parameter
16 * to ignore as a template argument. The default is to ignore the last
18 * (A value of @p -1 adds a parameter at the end so sigc::hide<-1>() gives the same result as sigc::hide().)
20 * The type of the parameter can optionally be specified if not deduced.
25 * // single argument hiding ...
26 * sigc::hide(&foo)(1,2,3); // adds a dummy parameter at the back and calls foo(1,2)
27 * sigc::hide<-1>(&foo)(1,2,3); // same as sigc::hide(&foo)(1,2,3) (calls foo(1,2))
28 * sigc::hide<0>(&foo)(1,2,3); // adds a dummy parameter at the beginning and calls foo(2,3)
29 * sigc::hide<1>(&foo)(1,2,3); // adds a dummy parameter in the middle and calls foo(1,3)
30 * sigc::hide<2>(&foo)(1,2,3); // adds a dummy parameter at the back and calls foo(1,2)
33 * The functor sigc::hide() returns can be directly passed into
34 * sigc::signal::connect().
38 * sigc::signal<void(int)> some_signal;
40 * some_signal.connect(sigc::hide(&foo));
43 * sigc::hide() can be nested in order to discard multiple arguments.
46 * // multiple argument hiding ...
47 * sigc::hide(sigc::hide(&foo))(1,2,3,4); // adds two dummy parameters at the back and calls foo(1,2)
50 * sigc::hide_return() alters an arbitrary functor by
51 * dropping its return value, thus converting it to a void functor.
57 /** Adaptor that adds a dummy parameter to the wrapped functor.
58 * Use the convenience function sigc::hide() to create an instance of sigc::hide_functor.
60 * The following template arguments are used:
61 * - @e I_location Zero-based position of the dummy parameter (@p -1 for the last parameter).
62 * - @e T_type Type of the dummy parameter.
63 * - @e T_functor Type of the functor to wrap.
67 template <int I_location, class T_functor>
68 struct hide_functor : public adapts<T_functor>
70 using adaptor_type = typename adapts<T_functor>::adaptor_type;
71 using result_type = typename adaptor_type::result_type;
73 /** Invokes the wrapped functor, ignoring the argument at index @e I_location (0-indexed).
74 * @param _A_a Arguments to be passed on to the functor, apart from the ignored argument.
75 * @return The return value of the functor invocation.
77 template <class... T_arg>
79 operator()(T_arg&&... _A_a)
81 constexpr auto size = sizeof...(T_arg);
82 constexpr auto index_ignore = (I_location == -1 ? size - 1 : I_location);
83 const auto t = std::tuple<T_arg...>(std::forward<T_arg>(_A_a)...);
85 const auto t_start = internal::tuple_start<index_ignore>(t);
86 const auto t_end = internal::tuple_end<size - index_ignore - 1>(t);
87 const auto t_used = std::tuple_cat(t_start, t_end);
89 constexpr auto size_used = size - 1;
91 //TODO: Remove these? They are just here as a sanity check.
92 static_assert(std::tuple_size<decltype(t_used)>::value == size_used, "Unexpected t_used size.");
94 const auto seq = std::make_index_sequence<size_used>();
95 return call_functor_operator_parentheses(t_used, seq);
98 /** Constructs a hide_functor object that adds a dummy parameter to the passed functor.
99 * @param _A_func Functor to invoke from operator()().
101 explicit hide_functor(const T_functor& _A_func)
102 : adapts<T_functor>(_A_func)
106 //TODO_variadic: Replace this with std::experimental::apply() if that becomes standard
107 //C++, or add our own implementation, to avoid code duplication.
108 template<class T_tuple, std::size_t... Is>
110 call_functor_operator_parentheses(T_tuple& tuple,
111 std::index_sequence<Is...>)
113 return this->functor_.template operator()(std::get<Is>(tuple)...);
118 #ifndef DOXYGEN_SHOULD_SKIP_THIS
119 //template specialization of visitor<>::do_visit_each<>(action, functor):
120 /** Performs a functor on each of the targets of a functor.
121 * The function overload for sigc::hide_functor performs a functor on the
122 * functor stored in the sigc::hide_functor object.
126 template <int I_location, class T_functor>
127 struct visitor<hide_functor<I_location, T_functor> >
129 template <typename T_action>
130 static void do_visit_each(const T_action& _A_action,
131 const hide_functor<I_location, T_functor>& _A_target)
133 sigc::visit_each(_A_action, _A_target.functor_);
136 #endif // DOXYGEN_SHOULD_SKIP_THIS
138 /** Creates an adaptor of type sigc::hide_functor which adds a dummy parameter to the passed functor.
139 * The optional template argument @e I_location specifies the zero-based
140 * position of the dummy parameter in the returned functor (@p -1 stands for the last parameter).
142 * @param _A_func Functor that should be wrapped.
143 * @return Adaptor that executes @e _A_func, ignoring the value of the dummy parameter.
147 template <int I_location, class T_functor>
148 inline decltype(auto)
149 hide(const T_functor& _A_func)
150 { return hide_functor<I_location, T_functor>(_A_func); }
152 /** Creates an adaptor of type sigc::hide_functor which adds a dummy parameter to the passed functor.
153 * This overload adds a dummy parameter at the back of the functor's parameter list.
155 * @param _A_func Functor that should be wrapped.
156 * @return Adaptor that executes @e _A_func, ignoring the value of the last parameter.
160 template <class T_functor>
161 inline decltype(auto)
162 hide(const T_functor& _A_func)
163 { return hide_functor<-1, T_functor> (_A_func); }
165 } /* namespace sigc */
167 #endif /* _SIGC_ADAPTORS_HIDE_H_ */