Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:52:43

0001 //  (C) Copyright Gennadiy Rozental 2001.
0002 //  Distributed under the Boost Software License, Version 1.0.
0003 //  (See accompanying file LICENSE_1_0.txt or copy at
0004 //  http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 //  See http://www.boost.org/libs/test for the library home page.
0007 //
0008 //  File        : $RCSfile$
0009 //
0010 //  Version     : $Revision$
0011 //
0012 //  Description : named function parameters library
0013 // ***************************************************************************
0014 
0015 #ifndef BOOST_TEST_UTILS_NAMED_PARAM
0016 #define BOOST_TEST_UTILS_NAMED_PARAM
0017 
0018 // Boost
0019 #include <boost/config.hpp>
0020 #include <boost/detail/workaround.hpp>
0021 
0022 // Boost.Test
0023 #include <boost/test/utils/rtti.hpp>
0024 #include <boost/test/utils/assign_op.hpp>
0025 
0026 #include <boost/type_traits/remove_reference.hpp>
0027 #include <boost/type_traits/remove_cv.hpp>
0028 
0029 #include <boost/test/detail/throw_exception.hpp>
0030 
0031 // Boost
0032 #include <boost/mpl/if.hpp>
0033 #include <boost/mpl/or.hpp>
0034 #include <boost/type_traits/is_same.hpp>
0035 #include <boost/type_traits/remove_cv.hpp>
0036 #include <boost/utility/enable_if.hpp>
0037 #include <boost/mpl/bool.hpp>
0038 
0039 #include <boost/test/detail/suppress_warnings.hpp>
0040 
0041 //____________________________________________________________________________//
0042 
0043 namespace boost {
0044 namespace nfp { // named function parameters
0045 
0046 // ************************************************************************** //
0047 // **************             forward declarations             ************** //
0048 // ************************************************************************** //
0049 
0050 template<typename unique_id, bool required>                     struct keyword;
0051 template<typename T, typename unique_id, bool required = false> struct typed_keyword;
0052 
0053 template<typename T, typename unique_id, typename RefType=T&>   struct named_parameter;
0054 template<typename NP1,typename NP2>                             struct named_parameter_combine;
0055 
0056 // ************************************************************************** //
0057 // **************              is_named_param_pack             ************** //
0058 // ************************************************************************** //
0059 
0060 /// is_named_param_pack<T>::value is true if T is parameters pack
0061 
0062 template<typename T>
0063 struct is_named_param_pack : public mpl::false_ {};
0064 
0065 template<typename T, typename unique_id, typename RefType>
0066 struct is_named_param_pack<named_parameter<T,unique_id,RefType> > : public mpl::true_ {};
0067 
0068 template<typename NP, typename Rest>
0069 struct is_named_param_pack<named_parameter_combine<NP,Rest> > : public mpl::true_ {};
0070 
0071 // ************************************************************************** //
0072 // **************                  param_type                  ************** //
0073 // ************************************************************************** //
0074 
0075 /// param_type<Params,Keyword,Default>::type is the type of the parameter
0076 /// corresponding to the Keyword (if parameter is present) or Default
0077 
0078 template<typename NP, typename Keyword, typename DefaultType=void>
0079 struct param_type
0080 : mpl::if_<typename is_same<typename NP::id,typename Keyword::id>::type,
0081            typename remove_cv<typename NP::data_type>::type,
0082            DefaultType> {};
0083 
0084 template<typename NP, typename Rest, typename Keyword, typename DefaultType>
0085 struct param_type<named_parameter_combine<NP,Rest>,Keyword,DefaultType>
0086 : mpl::if_<typename is_same<typename NP::id,typename Keyword::id>::type,
0087            typename remove_cv<typename NP::data_type>::type,
0088            typename param_type<Rest,Keyword,DefaultType>::type> {};
0089 
0090 // ************************************************************************** //
0091 // **************                  has_param                   ************** //
0092 // ************************************************************************** //
0093 
0094 /// has_param<Params,Keyword>::value is true if Params has parameter corresponding
0095 /// to the Keyword
0096 
0097 template<typename NP, typename Keyword>
0098 struct has_param : is_same<typename NP::id,typename Keyword::id> {};
0099 
0100 template<typename NP, typename Rest, typename Keyword>
0101 struct has_param<named_parameter_combine<NP,Rest>,Keyword>
0102 : mpl::or_<typename is_same<typename NP::id,typename Keyword::id>::type,
0103            typename has_param<Rest,Keyword>::type> {};
0104 
0105 // ************************************************************************** //
0106 // **************          access_to_invalid_parameter         ************** //
0107 // ************************************************************************** //
0108 
0109 namespace nfp_detail {
0110 
0111 struct access_to_invalid_parameter {};
0112 
0113 //____________________________________________________________________________//
0114 
0115 inline void
0116 report_access_to_invalid_parameter( bool v )
0117 {
0118     BOOST_TEST_I_ASSRT( !v, access_to_invalid_parameter() );
0119 }
0120 
0121 } // namespace nfp_detail
0122 
0123 // ************************************************************************** //
0124 // **************                      nil                     ************** //
0125 // ************************************************************************** //
0126 
0127 struct nil {
0128     template<typename T>
0129 #if defined(__GNUC__) || defined(__HP_aCC) || defined(__EDG__) || defined(__SUNPRO_CC) || defined(BOOST_EMBTC)
0130     operator T() const
0131 #else
0132     operator T const&() const
0133 #endif
0134     { nfp_detail::report_access_to_invalid_parameter(true); static T* v = 0; return *v; }
0135 
0136     template<typename T>
0137     T any_cast() const
0138     { nfp_detail::report_access_to_invalid_parameter(true); static typename remove_reference<T>::type* v = 0; return *v; }
0139 
0140     template<typename Arg1>
0141     nil operator()( Arg1 const& )
0142     { nfp_detail::report_access_to_invalid_parameter(true); return nil(); }
0143 
0144     template<typename Arg1,typename Arg2>
0145     nil operator()( Arg1 const&, Arg2 const& )
0146     { nfp_detail::report_access_to_invalid_parameter(true); return nil(); }
0147 
0148     template<typename Arg1,typename Arg2,typename Arg3>
0149     nil operator()( Arg1 const&, Arg2 const&, Arg3 const& )
0150     { nfp_detail::report_access_to_invalid_parameter(true); return nil(); }
0151 
0152     // Visitation support
0153     template<typename Visitor>
0154     void            apply_to( Visitor& /*v*/ ) const {}
0155 
0156     static nil&     inst() { static nil s_inst; return s_inst; }
0157 private:
0158     nil() {}
0159 };
0160 
0161 // ************************************************************************** //
0162 // **************             named_parameter_base             ************** //
0163 // ************************************************************************** //
0164 
0165 namespace nfp_detail {
0166 
0167 template<typename Derived>
0168 struct named_parameter_base {
0169     template<typename NP>
0170     named_parameter_combine<NP,Derived>
0171     operator,( NP const& np ) const { return named_parameter_combine<NP,Derived>( np, *static_cast<Derived const*>(this) ); }
0172 };
0173 
0174 } // namespace nfp_detail
0175 
0176 // ************************************************************************** //
0177 // **************            named_parameter_combine           ************** //
0178 // ************************************************************************** //
0179 
0180 template<typename NP, typename Rest = nil>
0181 struct named_parameter_combine
0182 : Rest
0183 , nfp_detail::named_parameter_base<named_parameter_combine<NP,Rest> > {
0184     typedef typename NP::ref_type  res_type;
0185     typedef named_parameter_combine<NP,Rest> self_type;
0186 
0187     // Constructor
0188     named_parameter_combine( NP const& np, Rest const& r )
0189     : Rest( r )
0190     , m_param( np )
0191     {
0192     }
0193 
0194     // Access methods
0195     res_type    operator[]( keyword<typename NP::id,true> kw ) const    { return m_param[kw]; }
0196     res_type    operator[]( keyword<typename NP::id,false> kw ) const   { return m_param[kw]; }
0197     using       Rest::operator[];
0198 
0199     bool        has( keyword<typename NP::id,false> kw ) const          { return m_param.has( kw ); }
0200     using       Rest::has;
0201 
0202     void        erase( keyword<typename NP::id,false> kw ) const        { m_param.erase( kw ); }
0203     using       Rest::erase;
0204 
0205     using       nfp_detail::named_parameter_base<named_parameter_combine<NP,Rest> >::operator,;
0206 
0207     // Visitation support
0208     template<typename Visitor>
0209     void            apply_to( Visitor& V ) const
0210     {
0211         m_param.apply_to( V );
0212 
0213         Rest::apply_to( V );
0214     }
0215 private:
0216     // Data members
0217     NP          m_param;
0218 };
0219 
0220 // ************************************************************************** //
0221 // **************                named_parameter               ************** //
0222 // ************************************************************************** //
0223 
0224 template<typename T, typename unique_id, typename RefType>
0225 struct named_parameter
0226 : nfp_detail::named_parameter_base<named_parameter<T,unique_id,RefType> >
0227 {
0228     typedef T               data_type;
0229     typedef RefType         ref_type;
0230     typedef unique_id       id;
0231 
0232     // Constructor
0233     explicit        named_parameter( ref_type v )
0234     : m_value( v )
0235     , m_erased( false )
0236     {}
0237     named_parameter( named_parameter const& np )
0238     : m_value( np.m_value )
0239     , m_erased( np.m_erased )
0240     {}
0241 
0242     // Access methods
0243     ref_type        operator[]( keyword<unique_id,true> ) const     { return m_erased ? nil::inst().template any_cast<ref_type>() :  m_value; }
0244     ref_type        operator[]( keyword<unique_id,false> ) const    { return m_erased ? nil::inst().template any_cast<ref_type>() :  m_value; }
0245     template<typename UnknownId>
0246     nil             operator[]( keyword<UnknownId,false> ) const    { return nil::inst(); }
0247 
0248     bool            has( keyword<unique_id,false> ) const           { return !m_erased; }
0249     template<typename UnknownId>
0250     bool            has( keyword<UnknownId,false> ) const           { return false; }
0251 
0252     void            erase( keyword<unique_id,false> ) const         { m_erased = true; }
0253     template<typename UnknownId>
0254     void            erase( keyword<UnknownId,false> ) const         {}
0255 
0256     // Visitation support
0257     template<typename Visitor>
0258     void            apply_to( Visitor& V ) const
0259     {
0260         V.set_parameter( rtti::type_id<unique_id>(), m_value );
0261     }
0262 
0263 private:
0264     // Data members
0265     ref_type        m_value;
0266     mutable bool    m_erased;
0267 };
0268 
0269 // ************************************************************************** //
0270 // **************                   no_params                  ************** //
0271 // ************************************************************************** //
0272 
0273 typedef named_parameter<char, struct no_params_type_t,char> no_params_type;
0274 
0275 namespace {
0276 no_params_type no_params( '\0' );
0277 } // local namespace
0278 
0279 // ************************************************************************** //
0280 // **************                    keyword                   ************** //
0281 // ************************************************************************** //
0282 
0283 template<typename unique_id, bool required = false>
0284 struct keyword {
0285     typedef unique_id id;
0286 
0287     template<typename T>
0288     named_parameter<T const,unique_id>
0289     operator=( T const& t ) const       { return named_parameter<T const,unique_id>( t ); }
0290 
0291     template<typename T>
0292     named_parameter<T,unique_id>
0293     operator=( T& t ) const             { return named_parameter<T,unique_id>( t ); }
0294 
0295     named_parameter<char const*,unique_id,char const*>
0296     operator=( char const* t ) const    { return named_parameter<char const*,unique_id,char const*>( t ); }
0297 };
0298 
0299 //____________________________________________________________________________//
0300 
0301 // ************************************************************************** //
0302 // **************                 typed_keyword                ************** //
0303 // ************************************************************************** //
0304 
0305 template<typename T, typename unique_id, bool required>
0306 struct typed_keyword : keyword<unique_id,required> {
0307     named_parameter<T const,unique_id>
0308     operator=( T const& t ) const       { return named_parameter<T const,unique_id>( t ); }
0309 
0310     named_parameter<T,unique_id>
0311     operator=( T& t ) const             { return named_parameter<T,unique_id>( t ); }
0312 };
0313 
0314 //____________________________________________________________________________//
0315 
0316 template<typename unique_id, bool required>
0317 struct typed_keyword<bool,unique_id,required>
0318 : keyword<unique_id,required>
0319 , named_parameter<bool,unique_id,bool> {
0320     typedef unique_id id;
0321 
0322     typed_keyword() : named_parameter<bool,unique_id,bool>( true ) {}
0323 
0324     named_parameter<bool,unique_id,bool>
0325     operator!() const           { return named_parameter<bool,unique_id,bool>( false ); }
0326 };
0327 
0328 // ************************************************************************** //
0329 // **************                  opt_assign                  ************** //
0330 // ************************************************************************** //
0331 
0332 template<typename T, typename Params, typename Keyword>
0333 inline typename enable_if_c<!has_param<Params,Keyword>::value,void>::type
0334 opt_assign( T& /*target*/, Params const& /*p*/, Keyword /*k*/ )
0335 {
0336 }
0337 
0338 //____________________________________________________________________________//
0339 
0340 template<typename T, typename Params, typename Keyword>
0341 inline typename enable_if_c<has_param<Params,Keyword>::value,void>::type
0342 opt_assign( T& target, Params const& p, Keyword k )
0343 {
0344     using namespace unit_test;
0345 
0346     assign_op( target, p[k], static_cast<int>(0) );
0347 }
0348 
0349 // ************************************************************************** //
0350 // **************                    opt_get                   ************** //
0351 // ************************************************************************** //
0352 
0353 template<typename T, typename Params, typename Keyword>
0354 inline T
0355 opt_get( Params const& p, Keyword k, T default_val )
0356 {
0357     opt_assign( default_val, p, k );
0358 
0359     return default_val;
0360 }
0361 
0362 // ************************************************************************** //
0363 // **************                    opt_get                   ************** //
0364 // ************************************************************************** //
0365 
0366 template<typename Params, typename NP>
0367 inline typename enable_if_c<!has_param<Params,keyword<typename NP::id> >::value,
0368 named_parameter_combine<NP,Params> >::type
0369 opt_append( Params const& params, NP const& np )
0370 {
0371     return (params,np);
0372 }
0373 
0374 //____________________________________________________________________________//
0375 
0376 template<typename Params, typename NP>
0377 inline typename enable_if_c<has_param<Params,keyword<typename NP::id> >::value,Params>::type
0378 opt_append( Params const& params, NP const& )
0379 {
0380     return params;
0381 }
0382 
0383 } // namespace nfp
0384 } // namespace boost
0385 
0386 #include <boost/test/detail/enable_warnings.hpp>
0387 
0388 #endif // BOOST_TEST_UTILS_NAMED_PARAM