| // (C) Copyright Gennadiy Rozental 2005-2008. |
| // 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) |
| |
| // See http://www.boost.org/libs/test for the library home page. |
| // |
| // File : $RCSfile$ |
| // |
| // Version : $Revision: 54633 $ |
| // |
| // Description : facilities for named function parameters support |
| // *************************************************************************** |
| |
| #ifndef NDNBOOST_TEST_NAMED_PARAM_022505GER |
| #define NDNBOOST_TEST_NAMED_PARAM_022505GER |
| |
| // Boost |
| #include <ndnboost/config.hpp> |
| #include <ndnboost/detail/workaround.hpp> |
| |
| // Boost.Test |
| #include <ndnboost/test/utils/rtti.hpp> |
| #include <ndnboost/test/utils/assign_op.hpp> |
| |
| #include <ndnboost/type_traits/remove_reference.hpp> |
| |
| #include <ndnboost/test/detail/suppress_warnings.hpp> |
| |
| //____________________________________________________________________________// |
| |
| namespace ndnboost { |
| |
| namespace nfp { // named function parameters |
| |
| // ************************************************************************** // |
| // ************** forward declarations ************** // |
| // ************************************************************************** // |
| |
| template<typename T, typename unique_id,typename RefType> struct named_parameter; |
| template<typename unique_id,bool required> struct keyword; |
| |
| namespace nfp_detail { |
| |
| template<typename NP1,typename NP2> struct named_parameter_combine; |
| |
| // ************************************************************************** // |
| // ************** access_to_invalid_parameter ************** // |
| // ************************************************************************** // |
| |
| struct access_to_invalid_parameter {}; |
| |
| //____________________________________________________________________________// |
| |
| inline void |
| report_access_to_invalid_parameter() |
| { |
| throw access_to_invalid_parameter(); |
| } |
| |
| //____________________________________________________________________________// |
| |
| // ************************************************************************** // |
| // ************** nil ************** // |
| // ************************************************************************** // |
| |
| struct nil { |
| template<typename T> |
| #if defined(__GNUC__) || defined(__HP_aCC) || defined(__EDG__) || defined(__SUNPRO_CC) |
| operator T() const |
| #else |
| operator T const&() const |
| #endif |
| { report_access_to_invalid_parameter(); static T* v = 0; return *v; } |
| |
| template<typename T> |
| T any_cast() const |
| { report_access_to_invalid_parameter(); static typename remove_reference<T>::type* v = 0; return *v; } |
| |
| template<typename Arg1> |
| nil operator()( Arg1 const& ) |
| { report_access_to_invalid_parameter(); return nil(); } |
| |
| template<typename Arg1,typename Arg2> |
| nil operator()( Arg1 const&, Arg2 const& ) |
| { report_access_to_invalid_parameter(); return nil(); } |
| |
| template<typename Arg1,typename Arg2,typename Arg3> |
| nil operator()( Arg1 const&, Arg2 const&, Arg3 const& ) |
| { report_access_to_invalid_parameter(); return nil(); } |
| |
| // Visitation support |
| template<typename Visitor> |
| void apply_to( Visitor& V ) const {} |
| |
| static nil& inst() { static nil s_inst; return s_inst; } |
| private: |
| nil() {} |
| }; |
| |
| // ************************************************************************** // |
| // ************** named_parameter_base ************** // |
| // ************************************************************************** // |
| |
| template<typename Derived> |
| struct named_parameter_base { |
| template<typename NP> |
| named_parameter_combine<NP,Derived> |
| operator,( NP const& np ) const { return named_parameter_combine<NP,Derived>( np, *static_cast<Derived const*>(this) ); } |
| }; |
| |
| //____________________________________________________________________________// |
| |
| // ************************************************************************** // |
| // ************** named_parameter_combine ************** // |
| // ************************************************************************** // |
| |
| template<typename NP, typename Rest = nil> |
| struct named_parameter_combine |
| : Rest |
| , named_parameter_base<named_parameter_combine<NP,Rest> > { |
| typedef typename NP::ref_type res_type; |
| typedef named_parameter_combine<NP,Rest> self_type; |
| |
| // Constructor |
| named_parameter_combine( NP const& np, Rest const& r ) |
| : Rest( r ) |
| , m_param( np ) |
| {} |
| |
| // Access methods |
| res_type operator[]( keyword<typename NP::id,true> kw ) const { return m_param[kw]; } |
| res_type operator[]( keyword<typename NP::id,false> kw ) const { return m_param[kw]; } |
| using Rest::operator[]; |
| |
| bool has( keyword<typename NP::id,false> kw ) const { return m_param.has( kw ); } |
| using Rest::has; |
| |
| void erase( keyword<typename NP::id,false> kw ) const { m_param.erase( kw ); } |
| using Rest::erase; |
| |
| #if NDNBOOST_WORKAROUND(__MWERKS__, NDNBOOST_TESTED_AT(0x3206)) || \ |
| NDNBOOST_WORKAROUND(__BORLANDC__, NDNBOOST_TESTED_AT(0x0610)) |
| template<typename NP> |
| named_parameter_combine<NP,self_type> operator,( NP const& np ) const |
| { return named_parameter_combine<NP,self_type>( np, *this ); } |
| #else |
| using named_parameter_base<named_parameter_combine<NP,Rest> >::operator,; |
| #endif |
| |
| // Visitation support |
| template<typename Visitor> |
| void apply_to( Visitor& V ) const |
| { |
| m_param.apply_to( V ); |
| |
| Rest::apply_to( V ); |
| } |
| private: |
| // Data members |
| NP m_param; |
| }; |
| |
| } // namespace nfp_detail |
| |
| // ************************************************************************** // |
| // ************** named_parameter ************** // |
| // ************************************************************************** // |
| |
| template<typename T, typename unique_id,typename ReferenceType=T&> |
| struct named_parameter |
| : nfp_detail::named_parameter_base<named_parameter<T, unique_id,ReferenceType> > |
| { |
| typedef nfp_detail::nil nil_t; |
| typedef T data_type; |
| typedef ReferenceType ref_type; |
| typedef unique_id id; |
| |
| // Constructor |
| explicit named_parameter( ref_type v ) |
| : m_value( v ) |
| , m_erased( false ) |
| {} |
| named_parameter( named_parameter const& np ) |
| : m_value( np.m_value ) |
| , m_erased( np.m_erased ) |
| {} |
| |
| // Access methods |
| ref_type operator[]( keyword<unique_id,true> ) const { return m_erased ? nil_t::inst().template any_cast<ref_type>() : m_value; } |
| ref_type operator[]( keyword<unique_id,false> ) const { return m_erased ? nil_t::inst().template any_cast<ref_type>() : m_value; } |
| template<typename UnknownId> |
| nil_t operator[]( keyword<UnknownId,false> ) const { return nil_t::inst(); } |
| |
| bool has( keyword<unique_id,false> ) const { return !m_erased; } |
| template<typename UnknownId> |
| bool has( keyword<UnknownId,false> ) const { return false; } |
| |
| void erase( keyword<unique_id,false> ) const { m_erased = true; } |
| template<typename UnknownId> |
| void erase( keyword<UnknownId,false> ) const {} |
| |
| // Visitation support |
| template<typename Visitor> |
| void apply_to( Visitor& V ) const |
| { |
| V.set_parameter( rtti::type_id<unique_id>(), m_value ); |
| } |
| |
| private: |
| // Data members |
| ref_type m_value; |
| mutable bool m_erased; |
| }; |
| |
| //____________________________________________________________________________// |
| |
| // ************************************************************************** // |
| // ************** no_params ************** // |
| // ************************************************************************** // |
| |
| namespace nfp_detail { |
| typedef named_parameter<char, struct no_params_type_t,char> no_params_type; |
| } // namespace nfp_detail |
| |
| namespace { |
| nfp_detail::no_params_type no_params( '\0' ); |
| } // local namespace |
| |
| //____________________________________________________________________________// |
| |
| // ************************************************************************** // |
| // ************** keyword ************** // |
| // ************************************************************************** // |
| |
| template<typename unique_id, bool required = false> |
| struct keyword { |
| typedef unique_id id; |
| |
| template<typename T> |
| named_parameter<T const,unique_id> |
| operator=( T const& t ) const { return named_parameter<T const,unique_id>( t ); } |
| |
| template<typename T> |
| named_parameter<T,unique_id> |
| operator=( T& t ) const { return named_parameter<T,unique_id>( t ); } |
| |
| named_parameter<char const*,unique_id,char const*> |
| operator=( char const* t ) const { return named_parameter<char const*,unique_id,char const*>( t ); } |
| }; |
| |
| //____________________________________________________________________________// |
| |
| // ************************************************************************** // |
| // ************** typed_keyword ************** // |
| // ************************************************************************** // |
| |
| template<typename T, typename unique_id, bool required = false> |
| struct typed_keyword : keyword<unique_id,required> { |
| named_parameter<T const,unique_id> |
| operator=( T const& t ) const { return named_parameter<T const,unique_id>( t ); } |
| |
| named_parameter<T,unique_id> |
| operator=( T& t ) const { return named_parameter<T,unique_id>( t ); } |
| }; |
| |
| //____________________________________________________________________________// |
| |
| template<typename unique_id> |
| struct typed_keyword<bool,unique_id,false> |
| : keyword<unique_id,false> |
| , named_parameter<bool,unique_id,bool> { |
| typedef unique_id id; |
| |
| typed_keyword() : named_parameter<bool,unique_id,bool>( true ) {} |
| |
| named_parameter<bool,unique_id,bool> |
| operator!() const { return named_parameter<bool,unique_id,bool>( false ); } |
| }; |
| |
| //____________________________________________________________________________// |
| |
| // ************************************************************************** // |
| // ************** optionally_assign ************** // |
| // ************************************************************************** // |
| |
| template<typename T> |
| inline void |
| optionally_assign( T&, nfp_detail::nil ) |
| { |
| nfp_detail::report_access_to_invalid_parameter(); |
| } |
| |
| //____________________________________________________________________________// |
| |
| template<typename T, typename Source> |
| inline void |
| #if NDNBOOST_WORKAROUND( __MWERKS__, NDNBOOST_TESTED_AT( 0x3003 ) ) \ |
| || NDNBOOST_WORKAROUND( __DECCXX_VER, NDNBOOST_TESTED_AT(60590042) ) |
| optionally_assign( T& target, Source src ) |
| #else |
| optionally_assign( T& target, Source const& src ) |
| #endif |
| { |
| using namespace unit_test; |
| |
| assign_op( target, src, static_cast<int>(0) ); |
| } |
| |
| //____________________________________________________________________________// |
| |
| template<typename T, typename Params, typename Keyword> |
| inline void |
| optionally_assign( T& target, Params const& p, Keyword k ) |
| { |
| if( p.has(k) ) |
| optionally_assign( target, p[k] ); |
| } |
| |
| //____________________________________________________________________________// |
| |
| } // namespace nfp |
| |
| } // namespace ndnboost |
| |
| #include <ndnboost/test/detail/enable_warnings.hpp> |
| |
| #endif // NDNBOOST_TEST_NAMED_PARAM_022505GER |
| |