From f22fa49e078b1bbef31e2a472135e17847ab578a Mon Sep 17 00:00:00 2001 From: Nikita Kniazev Date: Thu, 18 Oct 2018 21:44:22 +0300 Subject: [PATCH] Added variadic support Improves `boost/function.hpp` inclusion by 20%. --- include/boost/function.hpp | 4 +- .../boost/function/detail/maybe_include.hpp | 13 +++- include/boost/function/function_fwd.hpp | 16 +++++ include/boost/function/function_template.hpp | 70 ++++++++++++++++++- 4 files changed, 99 insertions(+), 4 deletions(-) diff --git a/include/boost/function.hpp b/include/boost/function.hpp index ef907e0..497ee96 100644 --- a/include/boost/function.hpp +++ b/include/boost/function.hpp @@ -29,8 +29,10 @@ // in anything that may be included by function_template.hpp doesn't break #include +#ifndef BOOST_FUNCTION_NO_VARIADIC +# include // Older Visual Age C++ version do not handle the file iteration well -#if BOOST_WORKAROUND(__IBMCPP__, >= 500) && BOOST_WORKAROUND(__IBMCPP__, < 800) +#elif BOOST_WORKAROUND(__IBMCPP__, >= 500) && BOOST_WORKAROUND(__IBMCPP__, < 800) # if BOOST_FUNCTION_MAX_ARGS >= 0 # include # endif diff --git a/include/boost/function/detail/maybe_include.hpp b/include/boost/function/detail/maybe_include.hpp index ec88905..df7eb7a 100644 --- a/include/boost/function/detail/maybe_include.hpp +++ b/include/boost/function/detail/maybe_include.hpp @@ -7,7 +7,18 @@ // For more information, see http://www.boost.org -#if BOOST_FUNCTION_NUM_ARGS == 0 +#include // for BOOST_FUNCTION_NO_VARIADIC + +#ifndef BOOST_FUNCTION_NO_VARIADIC +# undef BOOST_FUNCTION_NUM_ARGS +# define BOOST_FUNCTION_NUM_ARGS 50 +# undef BOOST_FUNCTION_MAX_ARGS_DEFINED +# define BOOST_FUNCTION_MAX_ARGS_DEFINED 50 +# ifndef BOOST_FUNCTION_VARIADIC_INCLUDED +# define BOOST_FUNCTION_VARIADIC_INCLUDED +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 0 # undef BOOST_FUNCTION_MAX_ARGS_DEFINED # define BOOST_FUNCTION_MAX_ARGS_DEFINED 0 # ifndef BOOST_FUNCTION_0 diff --git a/include/boost/function/function_fwd.hpp b/include/boost/function/function_fwd.hpp index e79b504..b31ec14 100644 --- a/include/boost/function/function_fwd.hpp +++ b/include/boost/function/function_fwd.hpp @@ -24,6 +24,12 @@ namespace boost { namespace python { namespace objects { # define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX #endif +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) +# define BOOST_FUNCTION_NO_VARIADIC +#else +# include // for functionN aliases generation below +#endif + namespace boost { class bad_function_call; @@ -38,6 +44,15 @@ namespace boost { } #endif // have partial specialization +#ifndef BOOST_FUNCTION_NO_VARIADIC + template class function_n; +# define BOOST_FUNCTION_N_ALIASES(z, N, d) \ + template \ + using function##N = function_n; + + BOOST_PP_REPEAT(51, BOOST_FUNCTION_N_ALIASES, ~) +# undef BOOST_FUNCTION_N_ALIASES +#else // Portable syntax template class function0; template class function1; @@ -64,6 +79,7 @@ namespace boost { typename T5, typename T6, typename T7, typename T8, typename T9, typename T10> class function10; +#endif } #endif diff --git a/include/boost/function/function_template.hpp b/include/boost/function/function_template.hpp index 56f6bb4..e90d393 100644 --- a/include/boost/function/function_template.hpp +++ b/include/boost/function/function_template.hpp @@ -18,6 +18,39 @@ # pragma warning( disable : 4127 ) // "conditional expression is constant" #endif +#ifndef BOOST_FUNCTION_NO_VARIADIC + +#define BOOST_FUNCTION_TEMPLATE_PARMS typename... T +#define BOOST_FUNCTION_TEMPLATE_ARGS T... +#define BOOST_FUNCTION_PARMS T... a +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES +# define BOOST_FUNCTION_ARGS a... +#else +# define BOOST_FUNCTION_ARGS static_cast(a)... +#endif + +// Always have commas (zero args case is handled with variadics too) +#define BOOST_FUNCTION_COMMA , + +// Class names used in this version of the code +#define BOOST_FUNCTION_FUNCTION function_n +#define BOOST_FUNCTION_FUNCTION_INVOKER function_invoker +#define BOOST_FUNCTION_VOID_FUNCTION_INVOKER void_function_invoker +#define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER function_obj_invoker +#define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER void_function_obj_invoker +#define BOOST_FUNCTION_FUNCTION_REF_INVOKER function_ref_invoker +#define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER void_function_ref_invoker +#define BOOST_FUNCTION_MEMBER_INVOKER function_mem_invoker +#define BOOST_FUNCTION_VOID_MEMBER_INVOKER function_void_mem_invoker +#define BOOST_FUNCTION_GET_FUNCTION_INVOKER get_function_invoker +#define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER get_function_obj_invoker +#define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER get_function_ref_invoker +#define BOOST_FUNCTION_GET_MEMBER_INVOKER get_member_invoker +#define BOOST_FUNCTION_GET_INVOKER get_invoker +#define BOOST_FUNCTION_VTABLE basic_vtable + +#else // BOOST_FUNCTION_NO_VARIADIC + #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T) #define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T) @@ -75,6 +108,8 @@ BOOST_JOIN(get_invoker,BOOST_FUNCTION_NUM_ARGS) #define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS) +#endif // BOOST_FUNCTION_NO_VARIADIC + #ifndef BOOST_NO_VOID_RETURNS # define BOOST_FUNCTION_VOID_RETURN_TYPE void # define BOOST_FUNCTION_RETURN(X) X @@ -652,6 +687,26 @@ namespace boost { vtable_base base; invoker_type invoker; }; + +#ifndef BOOST_FUNCTION_NO_VARIADIC + template + struct variadic_function_base + {}; + + template + struct variadic_function_base + { + typedef T argument_type; + }; + + template + struct variadic_function_base + { + typedef T0 first_argument_type; + typedef T1 second_argument_type; + }; +#endif + } // end namespace function } // end namespace detail @@ -660,6 +715,9 @@ namespace boost { BOOST_FUNCTION_TEMPLATE_PARMS > class BOOST_FUNCTION_FUNCTION : public function_base +#ifndef BOOST_FUNCTION_NO_VARIADIC + , public detail::function::variadic_function_base +#endif { public: #ifndef BOOST_NO_VOID_RETURNS @@ -682,8 +740,6 @@ namespace boost { struct clear_type {}; public: - BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS); - // add signature for boost::lambda template struct sig @@ -691,6 +747,13 @@ namespace boost { typedef result_type type; }; +#ifndef BOOST_FUNCTION_NO_VARIADIC + + static int const args = sizeof...(T); + static int const arity = sizeof...(T); + +#else + #if BOOST_FUNCTION_NUM_ARGS == 1 typedef T0 argument_type; #elif BOOST_FUNCTION_NUM_ARGS == 2 @@ -698,9 +761,12 @@ namespace boost { typedef T1 second_argument_type; #endif + BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS); BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS); BOOST_FUNCTION_ARG_TYPES +#endif + typedef BOOST_FUNCTION_FUNCTION self_type; BOOST_DEFAULTED_FUNCTION(BOOST_FUNCTION_FUNCTION(), : function_base() {})