Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:27

0001 ///////////////////////////////////////////////////////////////////////////////
0002 /// \file poly_function.hpp
0003 /// A wrapper that makes a tr1-style function object that handles const
0004 /// and non-const refs and reference_wrapper arguments, too, and forwards
0005 /// the arguments on to the specified implementation.
0006 //
0007 //  Copyright 2008 Eric Niebler. Distributed under the Boost
0008 //  Software License, Version 1.0. (See accompanying file
0009 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0010 
0011 #ifndef BOOST_PROTO_DETAIL_POLY_FUNCTION_EAN_2008_05_02
0012 #define BOOST_PROTO_DETAIL_POLY_FUNCTION_EAN_2008_05_02
0013 
0014 #include <boost/ref.hpp>
0015 #include <boost/mpl/bool.hpp>
0016 #include <boost/mpl/void.hpp>
0017 #include <boost/mpl/size_t.hpp>
0018 #include <boost/mpl/eval_if.hpp>
0019 #include <boost/preprocessor/cat.hpp>
0020 #include <boost/preprocessor/facilities/intercept.hpp>
0021 #include <boost/preprocessor/iteration/iterate.hpp>
0022 #include <boost/preprocessor/repetition/enum.hpp>
0023 #include <boost/preprocessor/repetition/enum_params.hpp>
0024 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
0025 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
0026 #include <boost/proto/proto_fwd.hpp>
0027 #include <boost/proto/detail/is_noncopyable.hpp>
0028 
0029 #ifdef _MSC_VER
0030 # pragma warning(push)
0031 # pragma warning(disable: 4181) // const applied to reference type
0032 #endif
0033 
0034 namespace boost { namespace proto { namespace detail
0035 {
0036 
0037     ////////////////////////////////////////////////////////////////////////////////////////////////
0038     template<typename T>
0039     struct normalize_arg
0040     {
0041         typedef typename mpl::if_c<is_noncopyable<T>::value, T &, T>::type type;
0042         typedef T &reference;
0043     };
0044 
0045     template<typename T>
0046     struct normalize_arg<T const>
0047     {
0048         typedef typename mpl::if_c<is_noncopyable<T>::value, T const &, T>::type type;
0049         typedef T const &reference;
0050     };
0051 
0052     template<typename T>
0053     struct normalize_arg<T &>
0054     {
0055         typedef typename mpl::if_c<is_noncopyable<T>::value, T &, T>::type type;
0056         typedef T &reference;
0057     };
0058 
0059     template<typename T>
0060     struct normalize_arg<T const &>
0061     {
0062         typedef typename mpl::if_c<is_noncopyable<T>::value, T const &, T>::type type;
0063         typedef T const &reference;
0064     };
0065 
0066     template<typename T>
0067     struct normalize_arg<boost::reference_wrapper<T> >
0068     {
0069         typedef T &type;
0070         typedef T &reference;
0071     };
0072 
0073     template<typename T>
0074     struct normalize_arg<boost::reference_wrapper<T> const>
0075     {
0076         typedef T &type;
0077         typedef T &reference;
0078     };
0079 
0080     template<typename T>
0081     struct normalize_arg<boost::reference_wrapper<T> &>
0082     {
0083         typedef T &type;
0084         typedef T &reference;
0085     };
0086 
0087     template<typename T>
0088     struct normalize_arg<boost::reference_wrapper<T> const &>
0089     {
0090         typedef T &type;
0091         typedef T &reference;
0092     };
0093 
0094     ////////////////////////////////////////////////////////////////////////////////////////////////
0095     template<typename T>
0096     struct arg
0097     {
0098         typedef T const &type;
0099 
0100         arg(type t)
0101           : value(t)
0102         {}
0103 
0104         operator type() const
0105         {
0106             return this->value;
0107         }
0108 
0109         type operator()() const
0110         {
0111             return this->value;
0112         }
0113 
0114         BOOST_DELETED_FUNCTION(arg &operator =(arg const &))
0115     private:
0116         type value;
0117     };
0118 
0119     template<typename T>
0120     struct arg<T &>
0121     {
0122         typedef T &type;
0123 
0124         arg(type t)
0125           : value(t)
0126         {}
0127 
0128         operator type() const
0129         {
0130             return this->value;
0131         }
0132 
0133         type operator()() const
0134         {
0135             return this->value;
0136         }
0137 
0138         BOOST_DELETED_FUNCTION(arg &operator =(arg const &))
0139     private:
0140         type value;
0141     };
0142 
0143     ////////////////////////////////////////////////////////////////////////////////////////////////
0144     template<typename T, typename Void = void>
0145     struct is_poly_function
0146       : mpl::false_
0147     {};
0148 
0149     template<typename T>
0150     struct is_poly_function<T, typename T::is_poly_function_base_>
0151       : mpl::true_
0152     {};
0153 
0154     ////////////////////////////////////////////////////////////////////////////////////////////////
0155     #define BOOST_PROTO_POLY_FUNCTION()                                                             \
0156         typedef void is_poly_function_base_;                                                        \
0157         /**/
0158 
0159     ////////////////////////////////////////////////////////////////////////////////////////////////
0160     struct poly_function_base
0161     {
0162         /// INTERNAL ONLY
0163         BOOST_PROTO_POLY_FUNCTION()
0164     };
0165 
0166     ////////////////////////////////////////////////////////////////////////////////////////////////
0167     template<typename Derived, typename NullaryResult = void>
0168     struct poly_function
0169       : poly_function_base
0170     {
0171         template<typename Sig>
0172         struct result;
0173 
0174         template<typename This>
0175         struct result<This()>
0176           : Derived::template impl<>
0177         {
0178             typedef typename result::result_type type;
0179         };
0180 
0181         NullaryResult operator()() const
0182         {
0183             result<Derived const()> impl;
0184             return impl();
0185         }
0186 
0187         #include <boost/proto/detail/poly_function_funop.hpp>
0188     };
0189 
0190     template<typename T>
0191     struct wrap_t;
0192 
0193     typedef char poly_function_t;
0194     typedef char (&mono_function_t)[2];
0195     typedef char (&unknown_function_t)[3];
0196 
0197     template<typename T> poly_function_t test_poly_function(T *, wrap_t<typename T::is_poly_function_base_> * = 0);
0198     template<typename T> mono_function_t test_poly_function(T *, wrap_t<typename T::result_type> * = 0);
0199     template<typename T> unknown_function_t test_poly_function(T *, ...);
0200 
0201     ////////////////////////////////////////////////////////////////////////////////////////////////
0202     template<typename Fun, typename Sig, typename Switch = mpl::size_t<sizeof(test_poly_function<Fun>(0,0))> >
0203     struct poly_function_traits
0204     {
0205         typedef typename Fun::template result<Sig>::type result_type;
0206         typedef Fun function_type;
0207     };
0208 
0209     ////////////////////////////////////////////////////////////////////////////////////////////////
0210     template<typename Fun, typename Sig>
0211     struct poly_function_traits<Fun, Sig, mpl::size_t<sizeof(mono_function_t)> >
0212     {
0213         typedef typename Fun::result_type result_type;
0214         typedef Fun function_type;
0215     };
0216 
0217     ////////////////////////////////////////////////////////////////////////////////////////////////
0218     template<typename PolyFunSig, bool IsPolyFunction>
0219     struct as_mono_function_impl;
0220 
0221     ////////////////////////////////////////////////////////////////////////////////////////////////
0222     template<typename PolyFunSig>
0223     struct as_mono_function;
0224 
0225     #include <boost/proto/detail/poly_function_traits.hpp>
0226 
0227 }}} // namespace boost::proto::detail
0228 
0229 #ifdef _MSC_VER
0230 # pragma warning(pop)
0231 #endif
0232 
0233 #endif
0234