Chris@16: // (C) Copyright Gennadiy Rozental 2005-2008. Chris@16: // Distributed under the Boost Software License, Version 1.0. Chris@16: // (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: // See http://www.boost.org/libs/test for the library home page. Chris@16: // Chris@16: // File : $RCSfile$ Chris@16: // Chris@101: // Version : $Revision$ Chris@16: // Chris@16: // Description : facilities for named function parameters support Chris@16: // *************************************************************************** Chris@16: Chris@16: #ifndef BOOST_TEST_NAMED_PARAM_022505GER Chris@16: #define BOOST_TEST_NAMED_PARAM_022505GER Chris@16: Chris@16: // Boost Chris@16: #include Chris@16: #include Chris@16: Chris@16: // Boost.Test Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: namespace nfp { // named function parameters Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** forward declarations ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: template struct named_parameter; Chris@16: template struct keyword; Chris@16: Chris@16: namespace nfp_detail { Chris@16: Chris@16: template struct named_parameter_combine; Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** access_to_invalid_parameter ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: struct access_to_invalid_parameter {}; Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: inline void Chris@16: report_access_to_invalid_parameter() Chris@16: { Chris@16: throw access_to_invalid_parameter(); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** nil ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: struct nil { Chris@16: template Chris@16: #if defined(__GNUC__) || defined(__HP_aCC) || defined(__EDG__) || defined(__SUNPRO_CC) Chris@16: operator T() const Chris@16: #else Chris@16: operator T const&() const Chris@16: #endif Chris@16: { report_access_to_invalid_parameter(); static T* v = 0; return *v; } Chris@16: Chris@16: template Chris@16: T any_cast() const Chris@16: { report_access_to_invalid_parameter(); static typename remove_reference::type* v = 0; return *v; } Chris@16: Chris@16: template Chris@16: nil operator()( Arg1 const& ) Chris@16: { report_access_to_invalid_parameter(); return nil(); } Chris@16: Chris@16: template Chris@16: nil operator()( Arg1 const&, Arg2 const& ) Chris@16: { report_access_to_invalid_parameter(); return nil(); } Chris@16: Chris@16: template Chris@16: nil operator()( Arg1 const&, Arg2 const&, Arg3 const& ) Chris@16: { report_access_to_invalid_parameter(); return nil(); } Chris@16: Chris@16: // Visitation support Chris@16: template Chris@16: void apply_to( Visitor& V ) const {} Chris@16: Chris@16: static nil& inst() { static nil s_inst; return s_inst; } Chris@16: private: Chris@16: nil() {} Chris@16: }; Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** named_parameter_base ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: template Chris@16: struct named_parameter_base { Chris@16: template Chris@16: named_parameter_combine Chris@16: operator,( NP const& np ) const { return named_parameter_combine( np, *static_cast(this) ); } Chris@16: }; Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** named_parameter_combine ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: template Chris@16: struct named_parameter_combine Chris@16: : Rest Chris@16: , named_parameter_base > { Chris@16: typedef typename NP::ref_type res_type; Chris@16: typedef named_parameter_combine self_type; Chris@16: Chris@16: // Constructor Chris@16: named_parameter_combine( NP const& np, Rest const& r ) Chris@16: : Rest( r ) Chris@16: , m_param( np ) Chris@16: {} Chris@16: Chris@16: // Access methods Chris@16: res_type operator[]( keyword kw ) const { return m_param[kw]; } Chris@16: res_type operator[]( keyword kw ) const { return m_param[kw]; } Chris@16: using Rest::operator[]; Chris@16: Chris@16: bool has( keyword kw ) const { return m_param.has( kw ); } Chris@16: using Rest::has; Chris@16: Chris@16: void erase( keyword kw ) const { m_param.erase( kw ); } Chris@16: using Rest::erase; Chris@16: Chris@16: #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) || \ Chris@16: BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0610)) Chris@16: template Chris@16: named_parameter_combine operator,( NP const& np ) const Chris@16: { return named_parameter_combine( np, *this ); } Chris@16: #else Chris@16: using named_parameter_base >::operator,; Chris@16: #endif Chris@16: Chris@16: // Visitation support Chris@16: template Chris@16: void apply_to( Visitor& V ) const Chris@16: { Chris@16: m_param.apply_to( V ); Chris@16: Chris@16: Rest::apply_to( V ); Chris@16: } Chris@16: private: Chris@16: // Data members Chris@16: NP m_param; Chris@16: }; Chris@16: Chris@16: } // namespace nfp_detail Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** named_parameter ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: template Chris@16: struct named_parameter Chris@16: : nfp_detail::named_parameter_base > Chris@16: { Chris@16: typedef nfp_detail::nil nil_t; Chris@16: typedef T data_type; Chris@16: typedef ReferenceType ref_type; Chris@16: typedef unique_id id; Chris@16: Chris@16: // Constructor Chris@16: explicit named_parameter( ref_type v ) Chris@16: : m_value( v ) Chris@16: , m_erased( false ) Chris@16: {} Chris@16: named_parameter( named_parameter const& np ) Chris@16: : m_value( np.m_value ) Chris@16: , m_erased( np.m_erased ) Chris@16: {} Chris@16: Chris@16: // Access methods Chris@16: ref_type operator[]( keyword ) const { return m_erased ? nil_t::inst().template any_cast() : m_value; } Chris@16: ref_type operator[]( keyword ) const { return m_erased ? nil_t::inst().template any_cast() : m_value; } Chris@16: template Chris@16: nil_t operator[]( keyword ) const { return nil_t::inst(); } Chris@16: Chris@16: bool has( keyword ) const { return !m_erased; } Chris@16: template Chris@16: bool has( keyword ) const { return false; } Chris@16: Chris@16: void erase( keyword ) const { m_erased = true; } Chris@16: template Chris@16: void erase( keyword ) const {} Chris@16: Chris@16: // Visitation support Chris@16: template Chris@16: void apply_to( Visitor& V ) const Chris@16: { Chris@16: V.set_parameter( rtti::type_id(), m_value ); Chris@16: } Chris@16: Chris@16: private: Chris@16: // Data members Chris@16: ref_type m_value; Chris@16: mutable bool m_erased; Chris@16: }; Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** no_params ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: namespace nfp_detail { Chris@16: typedef named_parameter no_params_type; Chris@16: } // namespace nfp_detail Chris@16: Chris@16: namespace { Chris@16: nfp_detail::no_params_type no_params( '\0' ); Chris@16: } // local namespace Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** keyword ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: template Chris@16: struct keyword { Chris@16: typedef unique_id id; Chris@16: Chris@16: template Chris@16: named_parameter Chris@16: operator=( T const& t ) const { return named_parameter( t ); } Chris@16: Chris@16: template Chris@16: named_parameter Chris@16: operator=( T& t ) const { return named_parameter( t ); } Chris@16: Chris@16: named_parameter Chris@16: operator=( char const* t ) const { return named_parameter( t ); } Chris@16: }; Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** typed_keyword ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: template Chris@16: struct typed_keyword : keyword { Chris@16: named_parameter Chris@16: operator=( T const& t ) const { return named_parameter( t ); } Chris@16: Chris@16: named_parameter Chris@16: operator=( T& t ) const { return named_parameter( t ); } Chris@16: }; Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: struct typed_keyword Chris@16: : keyword Chris@16: , named_parameter { Chris@16: typedef unique_id id; Chris@16: Chris@16: typed_keyword() : named_parameter( true ) {} Chris@16: Chris@16: named_parameter Chris@16: operator!() const { return named_parameter( false ); } Chris@16: }; Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** optionally_assign ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: template Chris@16: inline void Chris@16: optionally_assign( T&, nfp_detail::nil ) Chris@16: { Chris@16: nfp_detail::report_access_to_invalid_parameter(); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline void Chris@16: #if BOOST_WORKAROUND( __MWERKS__, BOOST_TESTED_AT( 0x3003 ) ) \ Chris@16: || BOOST_WORKAROUND( __DECCXX_VER, BOOST_TESTED_AT(60590042) ) Chris@16: optionally_assign( T& target, Source src ) Chris@16: #else Chris@16: optionally_assign( T& target, Source const& src ) Chris@16: #endif Chris@16: { Chris@16: using namespace unit_test; Chris@16: Chris@16: assign_op( target, src, static_cast(0) ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline void Chris@16: optionally_assign( T& target, Params const& p, Keyword k ) Chris@16: { Chris@16: if( p.has(k) ) Chris@16: optionally_assign( target, p[k] ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: } // namespace nfp Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // BOOST_TEST_NAMED_PARAM_022505GER Chris@16: