diff options
Diffstat (limited to 'boost/functional')
-rw-r--r-- | boost/functional/detail/container_fwd.hpp | 14 | ||||
-rw-r--r-- | boost/functional/hash/detail/container_fwd_0x.hpp | 29 | ||||
-rw-r--r-- | boost/functional/hash/detail/hash_float.hpp | 16 | ||||
-rw-r--r-- | boost/functional/hash/extensions.hpp | 101 | ||||
-rw-r--r-- | boost/functional/hash/hash.hpp | 172 | ||||
-rw-r--r-- | boost/functional/overloaded_function.hpp | 311 | ||||
-rw-r--r-- | boost/functional/overloaded_function/config.hpp | 50 | ||||
-rw-r--r-- | boost/functional/overloaded_function/detail/base.hpp | 86 | ||||
-rw-r--r-- | boost/functional/overloaded_function/detail/function_type.hpp | 85 |
9 files changed, 744 insertions, 120 deletions
diff --git a/boost/functional/detail/container_fwd.hpp b/boost/functional/detail/container_fwd.hpp index 9a69d155b2..e2bf86526c 100644 --- a/boost/functional/detail/container_fwd.hpp +++ b/boost/functional/detail/container_fwd.hpp @@ -1,11 +1,11 @@ -// Copyright 2005-2008 Daniel James. +// Copyright 2005-2012 Daniel James. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // Forwarding header for container_fwd.hpp's new location. -// This header is deprecated, I'll be adding a warning in a future release, -// then converting it to an error and finally removing this header completely. +// This header is deprecated, I'll change the warning to an error in a future +// release, and then later remove the header completely. #if !defined(BOOST_FUNCTIONAL_DETAIL_CONTAINER_FWD_HPP) #define BOOST_FUNCTIONAL_DETAIL_CONTAINER_FWD_HPP @@ -14,6 +14,14 @@ # pragma once #endif +#if defined(__EDG__) +#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) +#pragma message("Warning: boost/functional/detail/container_fwd.hpp is deprecated, use boost/detail/container_fwd.hpp instead.") +#elif defined(__GNUC__) || defined(__HP_aCC) || \ + defined(__SUNPRO_CC) || defined(__IBMCPP__) +#warning "boost/functional/detail/container_fwd.hpp is deprecated, use boost/detail/container_fwd.hpp instead." +#endif + #include <boost/detail/container_fwd.hpp> #endif diff --git a/boost/functional/hash/detail/container_fwd_0x.hpp b/boost/functional/hash/detail/container_fwd_0x.hpp new file mode 100644 index 0000000000..bed7730fc0 --- /dev/null +++ b/boost/functional/hash/detail/container_fwd_0x.hpp @@ -0,0 +1,29 @@ + +// Copyright 2012 Daniel James. +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_DETAIL_CONTAINER_FWD_0X_HPP) +#define BOOST_DETAIL_CONTAINER_FWD_0X_HPP + +#include <boost/detail/container_fwd.hpp> + +// std::array + +#if !defined(BOOST_NO_CXX11_HDR_ARRAY) +# include <array> +#endif + +// std::tuple + +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) +# include <tuple> +#endif + +// std::shared_ptr/std::unique_ptr + +#if !defined(BOOST_NO_CXX11_HDR_MEMORY) +# include <memory> +#endif + +#endif diff --git a/boost/functional/hash/detail/hash_float.hpp b/boost/functional/hash/detail/hash_float.hpp index ea1bc25f48..194be1cae5 100644 --- a/boost/functional/hash/detail/hash_float.hpp +++ b/boost/functional/hash/detail/hash_float.hpp @@ -87,9 +87,23 @@ namespace boost namespace hash_detail { template <class T> + inline bool is_zero(T v) + { +#if !defined(__GNUC__) + return v == 0; +#else + // GCC's '-Wfloat-equal' will complain about comparing + // v to 0, but because it disables warnings for system + // headers it won't complain if you use std::equal_to to + // compare with 0. Resulting in this silliness: + return std::equal_to<T>()(v, 0); +#endif + } + + template <class T> inline std::size_t float_hash_value(T v) { - return v == 0 ? 0 : float_hash_impl(v); + return boost::hash_detail::is_zero(v) ? 0 : float_hash_impl(v); } } } diff --git a/boost/functional/hash/extensions.hpp b/boost/functional/hash/extensions.hpp index 3c587a3bf5..4358736b26 100644 --- a/boost/functional/hash/extensions.hpp +++ b/boost/functional/hash/extensions.hpp @@ -14,7 +14,11 @@ #define BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP #include <boost/functional/hash/hash.hpp> -#include <boost/detail/container_fwd.hpp> +#include <boost/functional/hash/detail/container_fwd_0x.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/static_assert.hpp> +#include <boost/preprocessor/repetition/repeat_from_to.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once @@ -54,51 +58,51 @@ namespace boost std::size_t hash_value(std::pair<A, B> const& v) { std::size_t seed = 0; - hash_combine(seed, v.first); - hash_combine(seed, v.second); + boost::hash_combine(seed, v.first); + boost::hash_combine(seed, v.second); return seed; } template <class T, class A> std::size_t hash_value(std::vector<T, A> const& v) { - return hash_range(v.begin(), v.end()); + return boost::hash_range(v.begin(), v.end()); } template <class T, class A> std::size_t hash_value(std::list<T, A> const& v) { - return hash_range(v.begin(), v.end()); + return boost::hash_range(v.begin(), v.end()); } template <class T, class A> std::size_t hash_value(std::deque<T, A> const& v) { - return hash_range(v.begin(), v.end()); + return boost::hash_range(v.begin(), v.end()); } template <class K, class C, class A> std::size_t hash_value(std::set<K, C, A> const& v) { - return hash_range(v.begin(), v.end()); + return boost::hash_range(v.begin(), v.end()); } template <class K, class C, class A> std::size_t hash_value(std::multiset<K, C, A> const& v) { - return hash_range(v.begin(), v.end()); + return boost::hash_range(v.begin(), v.end()); } template <class K, class T, class C, class A> std::size_t hash_value(std::map<K, T, C, A> const& v) { - return hash_range(v.begin(), v.end()); + return boost::hash_range(v.begin(), v.end()); } template <class K, class T, class C, class A> std::size_t hash_value(std::multimap<K, T, C, A> const& v) { - return hash_range(v.begin(), v.end()); + return boost::hash_range(v.begin(), v.end()); } template <class T> @@ -110,6 +114,83 @@ namespace boost return seed; } +#if !defined(BOOST_NO_CXX11_HDR_ARRAY) + template <class T, std::size_t N> + std::size_t hash_value(std::array<T, N> const& v) + { + return boost::hash_range(v.begin(), v.end()); + } +#endif + +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) + namespace hash_detail { + template <std::size_t I, typename T> + inline typename boost::enable_if_c<(I == std::tuple_size<T>::value), + void>::type + hash_combine_tuple(std::size_t&, T const&) + { + } + + template <std::size_t I, typename T> + inline typename boost::enable_if_c<(I < std::tuple_size<T>::value), + void>::type + hash_combine_tuple(std::size_t& seed, T const& v) + { + boost::hash_combine(seed, std::get<I>(v)); + boost::hash_detail::hash_combine_tuple<I + 1>(seed, v); + } + + template <typename T> + inline std::size_t hash_tuple(T const& v) + { + std::size_t seed = 0; + boost::hash_detail::hash_combine_tuple<0>(seed, v); + return seed; + } + } + +#if !defined(BOOST_NO_VARIADIC_TEMPLATES) + template <typename... T> + inline std::size_t hash_value(std::tuple<T...> const& v) + { + return boost::hash_detail::hash_tuple(v); + } +#else + + inline std::size_t hash_value(std::tuple<> const& v) + { + return boost::hash_detail::hash_tuple(v); + } + +# define BOOST_HASH_TUPLE_F(z, n, _) \ + template< \ + BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \ + > \ + inline std::size_t hash_value(std::tuple< \ + BOOST_PP_ENUM_PARAMS_Z(z, n, A) \ + > const& v) \ + { \ + return boost::hash_detail::hash_tuple(v); \ + } + + BOOST_PP_REPEAT_FROM_TO(1, 11, BOOST_HASH_TUPLE_F, _) +# undef BOOST_HASH_TUPLE_F +#endif + +#endif + +#if !defined(BOOST_NO_CXX11_SMART_PTR) + template <typename T> + inline std::size_t hash_value(std::shared_ptr<T> const& x) { + return boost::hash_value(x.get()); + } + + template <typename T, typename Deleter> + inline std::size_t hash_value(std::unique_ptr<T, Deleter> const& x) { + return boost::hash_value(x.get()); + } +#endif + // // call_hash_impl // diff --git a/boost/functional/hash/hash.hpp b/boost/functional/hash/hash.hpp index 51ec8608c8..c179fab69a 100644 --- a/boost/functional/hash/hash.hpp +++ b/boost/functional/hash/hash.hpp @@ -16,15 +16,11 @@ #include <string> #include <boost/limits.hpp> -#if defined(BOOST_HASH_NO_IMPLICIT_CASTS) -#include <boost/static_assert.hpp> -#endif - #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) #include <boost/type_traits/is_pointer.hpp> #endif -#if !defined(BOOST_NO_0X_HDR_TYPEINDEX) +#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) #include <typeindex> #endif @@ -37,38 +33,63 @@ namespace boost { -#if defined(BOOST_HASH_NO_IMPLICIT_CASTS) - - // If you get a static assertion here, it's because hash_value - // isn't declared for your type. - template <typename T> - std::size_t hash_value(T const&) { - BOOST_STATIC_ASSERT((T*) 0 && false); - return 0; - } - -#endif - - std::size_t hash_value(bool); - std::size_t hash_value(char); - std::size_t hash_value(unsigned char); - std::size_t hash_value(signed char); - std::size_t hash_value(short); - std::size_t hash_value(unsigned short); - std::size_t hash_value(int); - std::size_t hash_value(unsigned int); - std::size_t hash_value(long); - std::size_t hash_value(unsigned long); + namespace hash_detail + { + struct enable_hash_value { typedef std::size_t type; }; + + template <typename T> struct basic_numbers {}; + template <typename T> struct long_numbers {}; + template <typename T> struct ulong_numbers {}; + template <typename T> struct float_numbers {}; + + template <> struct basic_numbers<bool> : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers<char> : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers<unsigned char> : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers<signed char> : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers<short> : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers<unsigned short> : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers<int> : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers<unsigned int> : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers<long> : + boost::hash_detail::enable_hash_value {}; + template <> struct basic_numbers<unsigned long> : + boost::hash_detail::enable_hash_value {}; #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) - std::size_t hash_value(wchar_t); + template <> struct basic_numbers<wchar_t> : + boost::hash_detail::enable_hash_value {}; #endif - + #if !defined(BOOST_NO_LONG_LONG) - std::size_t hash_value(boost::long_long_type); - std::size_t hash_value(boost::ulong_long_type); + template <> struct long_numbers<boost::long_long_type> : + boost::hash_detail::enable_hash_value {}; + template <> struct ulong_numbers<boost::ulong_long_type> : + boost::hash_detail::enable_hash_value {}; #endif + template <> struct float_numbers<float> : + boost::hash_detail::enable_hash_value {}; + template <> struct float_numbers<double> : + boost::hash_detail::enable_hash_value {}; + template <> struct float_numbers<long double> : + boost::hash_detail::enable_hash_value {}; + } + + template <typename T> + typename boost::hash_detail::basic_numbers<T>::type hash_value(T); + template <typename T> + typename boost::hash_detail::long_numbers<T>::type hash_value(T); + template <typename T> + typename boost::hash_detail::ulong_numbers<T>::type hash_value(T); + #if !BOOST_WORKAROUND(__DMC__, <= 0x848) template <class T> std::size_t hash_value(T* const&); #else @@ -83,15 +104,14 @@ namespace boost std::size_t hash_value(T (&x)[N]); #endif - std::size_t hash_value(float v); - std::size_t hash_value(double v); - std::size_t hash_value(long double v); - template <class Ch, class A> std::size_t hash_value( std::basic_string<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch>, A> const&); -#if !defined(BOOST_NO_0X_HDR_TYPEINDEX) + template <typename T> + typename boost::hash_detail::float_numbers<T>::type hash_value(T); + +#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) std::size_t hash_value(std::type_index); #endif @@ -141,74 +161,23 @@ namespace boost } } - inline std::size_t hash_value(bool v) - { - return static_cast<std::size_t>(v); - } - - inline std::size_t hash_value(char v) - { - return static_cast<std::size_t>(v); - } - - inline std::size_t hash_value(unsigned char v) - { - return static_cast<std::size_t>(v); - } - - inline std::size_t hash_value(signed char v) - { - return static_cast<std::size_t>(v); - } - - inline std::size_t hash_value(short v) - { - return static_cast<std::size_t>(v); - } - - inline std::size_t hash_value(unsigned short v) - { - return static_cast<std::size_t>(v); - } - - inline std::size_t hash_value(int v) - { - return static_cast<std::size_t>(v); - } - - inline std::size_t hash_value(unsigned int v) - { - return static_cast<std::size_t>(v); - } - - inline std::size_t hash_value(long v) - { - return static_cast<std::size_t>(v); - } - - inline std::size_t hash_value(unsigned long v) - { - return static_cast<std::size_t>(v); - } - -#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) - inline std::size_t hash_value(wchar_t v) + template <typename T> + typename boost::hash_detail::basic_numbers<T>::type hash_value(T v) { return static_cast<std::size_t>(v); } -#endif -#if !defined(BOOST_NO_LONG_LONG) - inline std::size_t hash_value(boost::long_long_type v) + template <typename T> + typename boost::hash_detail::long_numbers<T>::type hash_value(T v) { return hash_detail::hash_value_signed(v); } - inline std::size_t hash_value(boost::ulong_long_type v) + template <typename T> + typename boost::hash_detail::ulong_numbers<T>::type hash_value(T v) { return hash_detail::hash_value_unsigned(v); } -#endif // Implementation by Alberto Barbati and Dave Harris. #if !BOOST_WORKAROUND(__DMC__, <= 0x848) @@ -324,22 +293,13 @@ namespace boost return hash_range(v.begin(), v.end()); } - inline std::size_t hash_value(float v) - { - return boost::hash_detail::float_hash_value(v); - } - - inline std::size_t hash_value(double v) - { - return boost::hash_detail::float_hash_value(v); - } - - inline std::size_t hash_value(long double v) + template <typename T> + typename boost::hash_detail::float_numbers<T>::type hash_value(T v) { return boost::hash_detail::float_hash_value(v); } -#if !defined(BOOST_NO_0X_HDR_TYPEINDEX) +#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) inline std::size_t hash_value(std::type_index v) { return v.hash_code(); @@ -450,7 +410,7 @@ namespace boost BOOST_HASH_SPECIALIZE(boost::ulong_long_type) #endif -#if !defined(BOOST_NO_0X_HDR_TYPEINDEX) +#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) BOOST_HASH_SPECIALIZE(std::type_index) #endif diff --git a/boost/functional/overloaded_function.hpp b/boost/functional/overloaded_function.hpp new file mode 100644 index 0000000000..83fe4b3849 --- /dev/null +++ b/boost/functional/overloaded_function.hpp @@ -0,0 +1,311 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/functional/overloaded_function + +#ifndef DOXYGEN // Doxygen documentation only. + +#if !BOOST_PP_IS_ITERATING +# ifndef BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_HPP_ +# define BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_HPP_ + +# include <boost/functional/overloaded_function/detail/base.hpp> +# include <boost/functional/overloaded_function/detail/function_type.hpp> +# include <boost/functional/overloaded_function/config.hpp> +# include <boost/typeof/typeof.hpp> +# include <boost/preprocessor/iteration/iterate.hpp> +# include <boost/preprocessor/repetition/enum.hpp> +# include <boost/preprocessor/repetition/repeat.hpp> +# include <boost/preprocessor/control/expr_iif.hpp> +# include <boost/preprocessor/control/expr_if.hpp> +# include <boost/preprocessor/comparison/greater.hpp> +# include <boost/preprocessor/comparison/less.hpp> +# include <boost/preprocessor/cat.hpp> +# include <boost/preprocessor/arithmetic/add.hpp> +# include <boost/preprocessor/arithmetic/sub.hpp> +# include <boost/preprocessor/tuple/eat.hpp> +# include <boost/preprocessor/logical/and.hpp> +# include <boost/preprocessor/logical/not.hpp> +# include <boost/preprocessor/facilities/expand.hpp> + +#define BOOST_FUNCTIONAL_f_type(z, n, unused) \ + BOOST_PP_CAT(F, n) + +#define BOOST_FUNCTIONAL_f_arg(z, n, unused) \ + BOOST_PP_CAT(f, n) + +#define BOOST_FUNCTIONAL_f_tparam(z, n, unused) \ + typename BOOST_FUNCTIONAL_f_type(z, n, ~) \ + +#define BOOST_FUNCTIONAL_f_tparam_dflt(z, n, is_tspec) \ + BOOST_FUNCTIONAL_f_tparam(z, n, ~) \ + /* overload requires at least 2 functors so F0 and F1 not optional */ \ + BOOST_PP_EXPR_IIF(BOOST_PP_AND(BOOST_PP_NOT(is_tspec), \ + BOOST_PP_GREATER(n, 1)), \ + = void \ + ) + +#define BOOST_FUNCTIONAL_f_arg_decl(z, n, unused) \ + BOOST_FUNCTIONAL_f_type(z, n, ~) /* no qualifier to deduce tparam */ \ + BOOST_FUNCTIONAL_f_arg(z, n, ~) + +#define BOOST_FUNCTIONAL_g_type(z, n, unused) \ + BOOST_PP_CAT(G, n) + +#define BOOST_FUNCTIONAL_g_arg(z, n, unused) \ + BOOST_PP_CAT(g, n) + +#define BOOST_FUNCTIONAL_g_tparam(z, n, unused) \ + typename BOOST_FUNCTIONAL_g_type(z, n, ~) + +#define BOOST_FUNCTIONAL_g_arg_decl(z, n, unused) \ + BOOST_FUNCTIONAL_g_type(z, n, ~) /* no qualifier to deduce tparam */ \ + BOOST_FUNCTIONAL_g_arg(z, n, ~) + +#define BOOST_FUNCTIONAL_base(z, n, unused) \ + ::boost::overloaded_function_detail::base< \ + BOOST_FUNCTIONAL_f_type(z, n, ~) \ + > + +#define BOOST_FUNCTIONAL_inherit(z, n, unused) \ + public BOOST_FUNCTIONAL_base(z, n, ~) + +#define BOOST_FUNCTIONAL_base_init(z, n, unused) \ + BOOST_FUNCTIONAL_base(z, n, ~)(BOOST_FUNCTIONAL_g_arg(z, n, ~)) + +#define BOOST_FUNCTIONAL_using_operator_call(z, n, unused) \ + using BOOST_FUNCTIONAL_base(z, n, ~)::operator(); + +#define BOOST_FUNCTIONAL_function_type(z, n, unused) \ + typename ::boost::overloaded_function_detail::function_type< \ + BOOST_FUNCTIONAL_f_type(z, n, ~) \ + >::type + +# define BOOST_PP_ITERATION_PARAMS_1 \ + /* at least 2 func to overload so start from 2 to MAX */ \ + /* (cannot iterate [0, MAX-2) because error on Sun) */ \ + (3, (2, BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX, \ + "boost/functional/overloaded_function.hpp")) +# include BOOST_PP_ITERATE() // Iterate over function arity. + +#undef BOOST_FUNCTIONAL_f_type +#undef BOOST_FUNCTIONAL_f_arg +#undef BOOST_FUNCTIONAL_f_tparam +#undef BOOST_FUNCTIONAL_f_arg_decl +#undef BOOST_FUNCTIONAL_f_tparam_dflt +#undef BOOST_FUNCTIONAL_g_type +#undef BOOST_FUNCTIONAL_g_arg +#undef BOOST_FUNCTIONAL_g_tparam +#undef BOOST_FUNCTIONAL_g_arg_decl +#undef BOOST_FUNCTIONAL_base +#undef BOOST_FUNCTIONAL_inherit +#undef BOOST_FUNCTIONAL_base_init +#undef BOOST_FUNCTIONAL_using_operator_call +#undef BOOST_FUNCTIONAL_function_type + +# endif // #include guard + +#elif BOOST_PP_ITERATION_DEPTH() == 1 +# define BOOST_FUNCTIONAL_overloads \ + /* iterate as OVERLOADS, OVERLOADS-1, OVERLOADS-2, ... */ \ + /* (add 2 because iteration started from 2 to MAX) */ \ + BOOST_PP_ADD(2, BOOST_PP_SUB( \ + BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX, \ + BOOST_PP_FRAME_ITERATION(1))) +# define BOOST_FUNCTIONAL_is_tspec \ + /* if template specialization */ \ + BOOST_PP_LESS(BOOST_FUNCTIONAL_overloads, \ + BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX) + +// For type-of emulation: This must be included at this pp iteration level. +# include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() + +namespace boost { + +template< + BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_tparam_dflt, + BOOST_FUNCTIONAL_is_tspec) +> +class overloaded_function + // Template specialization. + BOOST_PP_EXPR_IIF(BOOST_PP_EXPAND(BOOST_FUNCTIONAL_is_tspec), <) + BOOST_PP_IIF(BOOST_FUNCTIONAL_is_tspec, + BOOST_PP_ENUM + , + BOOST_PP_TUPLE_EAT(3) + )(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_type, ~) + BOOST_PP_EXPR_IIF(BOOST_PP_EXPAND(BOOST_FUNCTIONAL_is_tspec), >) + // Bases (overloads >= 2 so always at least 2 bases). + : BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, + BOOST_FUNCTIONAL_inherit, ~) +{ +public: + template< + BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_g_tparam, ~) + > /* implicit */ inline overloaded_function( + BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, + BOOST_FUNCTIONAL_g_arg_decl, ~)) + // Overloads >= 2 so always at least 2 bases to initialize. + : BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, + BOOST_FUNCTIONAL_base_init, ~) + {} + + BOOST_PP_REPEAT(BOOST_FUNCTIONAL_overloads, + BOOST_FUNCTIONAL_using_operator_call, ~) +}; + +template< + BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_tparam, ~) +> +overloaded_function< + BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_function_type, ~) +> make_overloaded_function( + BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_arg_decl, ~) +) { + return overloaded_function< + BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, + BOOST_FUNCTIONAL_function_type, ~) + >(BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_arg, ~)); +} + +} // namespace + +// For type-of emulation: Register overloaded function type (for _AUTO, etc). +BOOST_TYPEOF_REGISTER_TEMPLATE(boost::overloaded_function, + BOOST_FUNCTIONAL_overloads) + +# undef BOOST_FUNCTIONAL_overloads +# undef BOOST_FUNCTIONAL_is_tspec +#endif // iteration + +// DOCUMENTATION // + +#else // DOXYGEN + +/** @file +@brief Overload distinct function pointers, function references, and +monomorphic function objects into a single function object. +*/ + +namespace boost { + +/** +@brief Function object to overload functions with distinct signatures. + +This function object aggregates together calls to functions of all the +specified function types <c>F1</c>, <c>F2</c>, etc which must have distinct +function signatures from one another. + +@Params +@Param{F<em>i</em>, +Each function type must be specified using the following syntax (which is +Boost.Function's preferred syntax): +@code + result_type (argument1_type\, argumgnet2_type\, ...) +@endcode +} +@EndParams + +In some cases, the @RefFunc{make_overloaded_function} function template can be +useful to construct an overloaded function object without explicitly +specifying the function types. + +At least two distinct function types must be specified (because there is +nothing to overload between one or zero functions). +The maximum number of functions to overload is given by the +@RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX} +configuration macro. +The maximum number of function parameters for each of the specified function +types is given by the +@RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_ARITY_MAX} +configuration macro. + +@See @RefSect{tutorial, Tutorial} section, @RefFunc{make_overloaded_function}, +@RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX}, +@RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_ARITY_MAX}, +Boost.Function. +*/ +template<typename F1, typename F2, ...> +class overloaded_function { +public: + /** + @brief Construct the overloaded function object. + + Any function pointer, function reference, and monomorphic function object + that can be converted to a <c>boost::function</c> function object can be + specified as parameter. + + @Note Unfortunately, it is not possible to support polymorphic function + objects (as explained <a + href="http://lists.boost.org/Archives/boost/2012/03/191744.php">here</a>). + */ + overloaded_function(const boost::function<F1>&, + const boost::function<F2>&, ...); + + /** + @brief Call operator matching the signature of the function type specified + as 1st template parameter. + + This will in turn invoke the call operator of the 1st function passed to + the constructor. + */ + typename boost::function_traits<F1>::result_type operator()( + typename boost::function_traits<F1>::arg1_type, + typename boost::function_traits<F1>::arg2_type, + ...) const; + + /** + @brief Call operator matching the signature of the function type specified + as 2nd template parameter. + + This will in turn invoke the call operator of the 2nd function passed to + the constructor. + + @Note Similar call operators are present for all specified function types + <c>F1</c>, <c>F2</c>, etc (even if not exhaustively listed by this + documentation). + */ + typename boost::function_traits<F2>::result_type operator()( + typename boost::function_traits<F2>::arg1_type, + typename boost::function_traits<F2>::arg2_type, + ...) const; +}; + +/** +@brief Make an overloaded function object without explicitly specifying the +function types. + +This function template creates and returns an @RefClass{overloaded_function} +object that overloads all the specified functions <c>f1</c>, <c>f2</c>, etc. + +The function types are internally determined from the template parameter types +so they do not need to be explicitly specified. +Therefore, this function template usually has a more concise syntax when +compared with @RefClass{overloaded_function}. +This is especially useful when the explicit type of the returned +@RefClass{overloaded_function} object does not need to be known (e.g., when +used with Boost.Typeof's <c>BOOST_AUTO</c>, C++11 <c>auto</c>, or when the +overloaded function object is handled using a function template parameter, see +the @RefSect{tutorial, Tutorial} section). + +The maximum number of functions to overload is given by the +@RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX} +configuration macro. + +@Note In this documentation, <c>__function_type__</c> is a placeholder for a +symbol that is specific to the implementation of this library. + +@See @RefSect{tutorial, Tutorial} section, @RefClass{overloaded_function}, +@RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX}. +*/ +template<typename F1, typename F2, ...> +overloaded_function< + __function_type__<F1>, __function_type__<F2>, ... +> make_overloaded_function(F1 f1, F2 f2, ...); + +} // namespace + +#endif // DOXYGEN + diff --git a/boost/functional/overloaded_function/config.hpp b/boost/functional/overloaded_function/config.hpp new file mode 100644 index 0000000000..2f5d9e1323 --- /dev/null +++ b/boost/functional/overloaded_function/config.hpp @@ -0,0 +1,50 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/functional/overloaded_function + +#ifndef BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_HPP_ +#define BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_HPP_ + +/** @file +@brief Change the compile-time configuration of this library. +*/ + +/** +@brief Specify the maximum number of arguments of the functions being +overloaded. + +If this macro is left undefined by the user, it has a default value of 5 +(increasing this number might increase compilation time). +When specified by the user, this macro must be a non-negative integer number. + +@See @RefSect{getting_started, Getting Started}, +@RefClass{boost::overloaded_function}. +*/ +#ifndef BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_ARITY_MAX +# define BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_ARITY_MAX 5 +#endif + +/** +@brief Specify the maximum number of functions that can be overloaded. + +If this macro is left undefined by the user, it has a default value of 5 +(increasing this number might increase compilation time). +When defined by the user, this macro must be an integer number greater or +equal than 2 (because at least two distinct functions need to be specified in +order to define an overload). + +@See @RefSect{getting_started, Getting Started}, +@RefClass{boost::overloaded_function}. +*/ +#ifndef BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX +# define BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX 5 +#endif +#if BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX < 2 +# error "maximum overload macro cannot be less than 2" +#endif + +#endif // #include guard + diff --git a/boost/functional/overloaded_function/detail/base.hpp b/boost/functional/overloaded_function/detail/base.hpp new file mode 100644 index 0000000000..8fd9a0a2c9 --- /dev/null +++ b/boost/functional/overloaded_function/detail/base.hpp @@ -0,0 +1,86 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/functional/overloaded_function + +#if !BOOST_PP_IS_ITERATING +# ifndef BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_DETAIL_BASE_HPP_ +# define BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_DETAIL_BASE_HPP_ + +# include <boost/functional/overloaded_function/config.hpp> +# include <boost/function.hpp> +# include <boost/preprocessor/iteration/iterate.hpp> +# include <boost/preprocessor/repetition/enum.hpp> +# include <boost/preprocessor/cat.hpp> +# include <boost/preprocessor/comma_if.hpp> + +#define BOOST_FUNCTIONAL_DETAIL_arg_type(z, n, unused) \ + BOOST_PP_CAT(A, n) + +#define BOOST_FUNCTIONAL_DETAIL_arg_name(z, n, unused) \ + BOOST_PP_CAT(a, n) + +#define BOOST_FUNCTIONAL_DETAIL_arg_tparam(z, n, unused) \ + typename BOOST_FUNCTIONAL_DETAIL_arg_type(z, n, unused) + +#define BOOST_FUNCTIONAL_DETAIL_arg(z, n, unused) \ + BOOST_FUNCTIONAL_DETAIL_arg_type(z, n, unused) \ + BOOST_FUNCTIONAL_DETAIL_arg_name(z, n, unused) + +#define BOOST_FUNCTIONAL_DETAIL_f \ + R (BOOST_PP_ENUM(BOOST_FUNCTIONAL_DETAIL_arity, \ + BOOST_FUNCTIONAL_DETAIL_arg_type, ~)) + +// Do not use namespace ::detail because overloaded_function is already a class. +namespace boost { namespace overloaded_function_detail { + +template<typename F> +class base {}; // Empty template cannot be used directly (only its spec). + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_ARITY_MAX, \ + "boost/functional/overloaded_function/detail/base.hpp")) +# include BOOST_PP_ITERATE() // Iterate over funciton arity. + +} } // namespace + +#undef BOOST_FUNCTIONAL_DETAIL_arg_type +#undef BOOST_FUNCTIONAL_DETAIL_arg_name +#undef BOOST_FUNCTIONAL_DETAIL_arg_tparam +#undef BOOST_FUNCTIONAL_DETAIL_arg +#undef BOOST_FUNCTIONAL_DETAIL_f + +# endif // #include guard + +#elif BOOST_PP_ITERATION_DEPTH() == 1 +# define BOOST_FUNCTIONAL_DETAIL_arity BOOST_PP_FRAME_ITERATION(1) + +template< + typename R + BOOST_PP_COMMA_IF(BOOST_FUNCTIONAL_DETAIL_arity) + BOOST_PP_ENUM(BOOST_FUNCTIONAL_DETAIL_arity, + BOOST_FUNCTIONAL_DETAIL_arg_tparam, ~) +> +class base< BOOST_FUNCTIONAL_DETAIL_f > { +public: + /* implicit */ inline base( + // This requires specified type to be implicitly convertible to + // a boost::function<> functor. + boost::function< BOOST_FUNCTIONAL_DETAIL_f > const& f): f_(f) + {} + + inline R operator()(BOOST_PP_ENUM(BOOST_FUNCTIONAL_DETAIL_arity, + BOOST_FUNCTIONAL_DETAIL_arg, ~)) const { + return f_(BOOST_PP_ENUM(BOOST_FUNCTIONAL_DETAIL_arity, + BOOST_FUNCTIONAL_DETAIL_arg_name, ~)); + } + +private: + boost::function< BOOST_FUNCTIONAL_DETAIL_f > const f_; +}; + +# undef BOOST_FUNCTIONAL_DETAIL_arity +#endif // iteration + diff --git a/boost/functional/overloaded_function/detail/function_type.hpp b/boost/functional/overloaded_function/detail/function_type.hpp new file mode 100644 index 0000000000..0c28607b88 --- /dev/null +++ b/boost/functional/overloaded_function/detail/function_type.hpp @@ -0,0 +1,85 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/functional/overloaded_function + +#ifndef BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_DETAIL_FUNCTION_TYPE_HPP_ +#define BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_DETAIL_FUNCTION_TYPE_HPP_ + +#include <boost/function_types/is_function.hpp> +#include <boost/function_types/is_function_pointer.hpp> +#include <boost/function_types/is_function_reference.hpp> +#include <boost/function_types/function_type.hpp> +#include <boost/function_types/parameter_types.hpp> +#include <boost/function_types/result_type.hpp> +#include <boost/type_traits/remove_pointer.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/function.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/identity.hpp> +#include <boost/mpl/pop_front.hpp> +#include <boost/mpl/push_front.hpp> +#include <boost/typeof/typeof.hpp> + +// Do not use namespace ::detail because overloaded_function is already a class. +namespace boost { namespace overloaded_function_detail { + +// Requires: F is a monomorphic functor (i.e., has non-template `operator()`). +// Returns: F's function type `result_type (arg1_type, arg2_type, ...)`. +// It does not assume F typedef result_type, arg1_type, ... but needs typeof. +template<typename F> +class functor_type { + // NOTE: clang does not accept extra parenthesis `&(...)`. + typedef BOOST_TYPEOF_TPL(&F::operator()) call_ptr; +public: + typedef + typename boost::function_types::function_type< + typename boost::mpl::push_front< + typename boost::mpl::pop_front< // Remove functor type (1st). + typename boost::function_types::parameter_types< + call_ptr>::type + >::type + , typename boost::function_types::result_type<call_ptr>::type + >::type + >::type + type; +}; + +// NOTE: When using boost::function in Boost.Typeof emulation mode, the user +// has to register boost::functionN instead of boost::function in oder to +// do TYPEOF(F::operator()). That is confusing, so boost::function is handled +// separately so it does not require any Boost.Typeof registration at all. +template<typename F> +struct functor_type< boost::function<F> > { + typedef F type; +}; + +// Requires: F is a function type, pointer, reference, or monomorphic functor. +// Returns: F's function type `result_type (arg1_type, arg2_type, ...)`. +template<typename F> +struct function_type { + typedef + typename boost::mpl::if_<boost::function_types::is_function<F>, + boost::mpl::identity<F> + , + typename boost::mpl::if_<boost::function_types:: + is_function_pointer<F>, + boost::remove_pointer<F> + , + typename boost::mpl::if_<boost::function_types:: + is_function_reference<F>, + boost::remove_reference<F> + , // Else, requires that F is a functor. + functor_type<F> + >::type + >::type + >::type + ::type type; +}; + +} } // namespace + +#endif // #include guard + |