diff options
author | Murray Cumming <murrayc@murrayc.com> | 2016-01-14 17:37:59 +0100 |
---|---|---|
committer | Murray Cumming <murrayc@murrayc.com> | 2016-03-01 22:26:07 +0100 |
commit | 6f429d66aa27351bb555b1bcf95ca7c1fe4016a2 (patch) | |
tree | 0a805e8ca2e5e759a87cbd2ede5d7231a8d22605 | |
parent | 8601c79725ab426b3bccd5f09b59b0b0e19629a8 (diff) | |
download | sigc++-6f429d66aa27351bb555b1bcf95ca7c1fe4016a2.tar.gz |
hide_functor: Make this fully variadic.
-rw-r--r-- | sigc++/adaptors/macros/hide.h.m4 | 135 |
1 files changed, 58 insertions, 77 deletions
diff --git a/sigc++/adaptors/macros/hide.h.m4 b/sigc++/adaptors/macros/hide.h.m4 index b37cadc..3ed7508 100644 --- a/sigc++/adaptors/macros/hide.h.m4 +++ b/sigc++/adaptors/macros/hide.h.m4 @@ -25,77 +25,6 @@ ifelse($1,0,,$1)ifelse($1,0,[last],$1,1,[st],$1,2,[nd],$1,3,[rd],[th])[]dnl ])])dnl ])dnl end HIDE_OPERATOR -define([HIDE_FUNCTOR],[dnl -ifelse($1,1,[#ifndef DOXYGEN_SHOULD_SKIP_THIS -],)dnl Include only the first two template specializations in the documentation. ($1 = -1..CALL_SIZE-1) -/** Adaptor that adds a dummy parameter to the wrapped functor. - * This template specialization ignores the value of the ORDINAL(eval($1+1)) parameter in operator()(). - * - * @ingroup hide - */ -template <class T_functor> -struct hide_functor <$1, T_functor> : public adapts<T_functor> -{ - typedef typename adapts<T_functor>::adaptor_type adaptor_type; - typedef typename adaptor_type::result_type result_type; - - /** Invokes the wrapped functor, ignoring the ORDINAL($1) argument.dnl - * @param _A_a Arguments to be passed on to the functor, apart from the ORDINAL($1) argument. - * @return The return value of the functor invocation. - */ - template <class... T_arg> - decltype(auto) - operator()(T_arg... _A_a) - { - constexpr auto size = sizeof...(T_arg); - constexpr auto index_ignore = ($1 == -1 ? size - 1 : $1); - const auto t = std::make_tuple(_A_a...); - - const auto t_start = tuple_start<index_ignore>(t); - const auto t_end = tuple_end<size - index_ignore - 1>(t); - auto t_used = std::tuple_cat(t_start, t_end); //TODO: Let this be const? - - //This is so we can specify a particular instantiation of the functor's - //operator(). - //TODO: Avoid this if it no longer necessary. - using t_type = std::tuple<type_trait_pass_t<T_arg>...>; - using t_type_start = typename tuple_type_start<t_type, index_ignore>::type; - using t_type_end = typename tuple_type_end<t_type, size - index_ignore - 1>::type; - using t_type_used = typename tuple_type_cat<t_type_start, t_type_end>::type; - - constexpr auto size_used = size - 1; - - //TODO: Remove these? They are just here as a sanity check. - static_assert(std::tuple_size<t_type_used>::value == size_used, "Unexpected t_type_used size."); - static_assert(std::tuple_size<decltype(t_used)>::value == size_used, "Unexpected t_used size."); - - const auto seq = std::make_index_sequence<size_used>(); - return call_functor_operator_parentheses<t_type_used>(t_used, seq); - } - - /** Constructs a hide_functor object that adds a dummy parameter to the passed functor. - * @param _A_func Functor to invoke from operator()(). - */ - explicit hide_functor(const T_functor& _A_func) - : adapts<T_functor>(_A_func) - {} - -private: - //TODO_variadic: Replace this with std::experimental::apply() if that becomes standard - //C++, or add our own implementation, to avoid code duplication. - template<class T_tuple_specific, class T_tuple, std::size_t... Is> - decltype(auto) - call_functor_operator_parentheses(T_tuple& tuple, - std::index_sequence<Is...>) - { - return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES<typename std::tuple_element<Is, T_tuple_specific>::type...>(std::get<Is>(tuple)...); - } -}; -ifelse($1,eval(CALL_SIZE-1),[#endif // DOXYGEN_SHOULD_SKIP_THIS -],)dnl Include only the first two template specializations in the documentation. ($1 = -1..CALL_SIZE-1) - -])dnl end HIDE_FUNCTOR - divert(0)dnl _FIREWALL([ADAPTORS_HIDE]) #include <sigc++/adaptors/adaptor_trait.h> @@ -151,6 +80,7 @@ namespace sigc { * @ingroup adaptors */ + /** Adaptor that adds a dummy parameter to the wrapped functor. * Use the convenience function sigc::hide() to create an instance of sigc::hide_functor. * @@ -162,13 +92,64 @@ namespace sigc { * @ingroup hide */ template <int I_location, class T_functor> -#ifndef DOXYGEN_SHOULD_SKIP_THIS -struct hide_functor; -#else -struct hide_functor {}; -#endif +struct hide_functor : public adapts<T_functor> +{ + typedef typename adapts<T_functor>::adaptor_type adaptor_type; + typedef typename adaptor_type::result_type result_type; + + /** Invokes the wrapped functor, ignoring the argument at index @e I_location (0-indexed). + * @param _A_a Arguments to be passed on to the functor, apart from the ignored argument. + * @return The return value of the functor invocation. + */ + template <class... T_arg> + decltype(auto) + operator()(T_arg... _A_a) + { + constexpr auto size = sizeof...(T_arg); + constexpr auto index_ignore = (I_location == -1 ? size - 1 : I_location); + const auto t = std::make_tuple(_A_a...); + + const auto t_start = tuple_start<index_ignore>(t); + const auto t_end = tuple_end<size - index_ignore - 1>(t); + auto t_used = std::tuple_cat(t_start, t_end); //TODO: Let this be const? + + //This is so we can specify a particular instantiation of the functor's + //operator(). + //TODO: Avoid this if it no longer necessary. + using t_type = std::tuple<type_trait_pass_t<T_arg>...>; + using t_type_start = typename tuple_type_start<t_type, index_ignore>::type; + using t_type_end = typename tuple_type_end<t_type, size - index_ignore - 1>::type; + using t_type_used = typename tuple_type_cat<t_type_start, t_type_end>::type; + + constexpr auto size_used = size - 1; + + //TODO: Remove these? They are just here as a sanity check. + static_assert(std::tuple_size<t_type_used>::value == size_used, "Unexpected t_type_used size."); + static_assert(std::tuple_size<decltype(t_used)>::value == size_used, "Unexpected t_used size."); + + const auto seq = std::make_index_sequence<size_used>(); + return call_functor_operator_parentheses<t_type_used>(t_used, seq); + } + + /** Constructs a hide_functor object that adds a dummy parameter to the passed functor. + * @param _A_func Functor to invoke from operator()(). + */ + explicit hide_functor(const T_functor& _A_func) + : adapts<T_functor>(_A_func) + {} + +private: + //TODO_variadic: Replace this with std::experimental::apply() if that becomes standard + //C++, or add our own implementation, to avoid code duplication. + template<class T_tuple_specific, class T_tuple, std::size_t... Is> + decltype(auto) + call_functor_operator_parentheses(T_tuple& tuple, + std::index_sequence<Is...>) + { + return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES<typename std::tuple_element<Is, T_tuple_specific>::type...>(std::get<Is>(tuple)...); + } +}; -FOR(-1,eval(CALL_SIZE-1),[[HIDE_FUNCTOR(%1)]])dnl #ifndef DOXYGEN_SHOULD_SKIP_THIS //template specialization of visitor<>::do_visit_each<>(action, functor): |