named_params.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. // (C) Copyright Gennadiy Rozental 2005-2008.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // See http://www.boost.org/libs/test for the library home page.
  6. //
  7. // File : $RCSfile$
  8. //
  9. // Version : $Revision: 54633 $
  10. //
  11. // Description : facilities for named function parameters support
  12. // ***************************************************************************
  13. #ifndef BOOST_TEST_NAMED_PARAM_022505GER
  14. #define BOOST_TEST_NAMED_PARAM_022505GER
  15. // Boost
  16. #include <boost/config.hpp>
  17. #include <boost/detail/workaround.hpp>
  18. // Boost.Test
  19. #include <boost/test/utils/rtti.hpp>
  20. #include <boost/test/utils/assign_op.hpp>
  21. #include <boost/type_traits/remove_reference.hpp>
  22. #include <boost/test/detail/suppress_warnings.hpp>
  23. //____________________________________________________________________________//
  24. namespace boost {
  25. namespace nfp { // named function parameters
  26. // ************************************************************************** //
  27. // ************** forward declarations ************** //
  28. // ************************************************************************** //
  29. template<typename T, typename unique_id,typename RefType> struct named_parameter;
  30. template<typename unique_id,bool required> struct keyword;
  31. namespace nfp_detail {
  32. template<typename NP1,typename NP2> struct named_parameter_combine;
  33. // ************************************************************************** //
  34. // ************** access_to_invalid_parameter ************** //
  35. // ************************************************************************** //
  36. struct access_to_invalid_parameter {};
  37. //____________________________________________________________________________//
  38. inline void
  39. report_access_to_invalid_parameter()
  40. {
  41. throw access_to_invalid_parameter();
  42. }
  43. //____________________________________________________________________________//
  44. // ************************************************************************** //
  45. // ************** nil ************** //
  46. // ************************************************************************** //
  47. struct nil {
  48. template<typename T>
  49. #if defined(__GNUC__) || defined(__HP_aCC) || defined(__EDG__) || defined(__SUNPRO_CC)
  50. operator T() const
  51. #else
  52. operator T const&() const
  53. #endif
  54. { report_access_to_invalid_parameter(); static T* v = 0; return *v; }
  55. template<typename T>
  56. T any_cast() const
  57. { report_access_to_invalid_parameter(); static typename remove_reference<T>::type* v = 0; return *v; }
  58. template<typename Arg1>
  59. nil operator()( Arg1 const& )
  60. { report_access_to_invalid_parameter(); return nil(); }
  61. template<typename Arg1,typename Arg2>
  62. nil operator()( Arg1 const&, Arg2 const& )
  63. { report_access_to_invalid_parameter(); return nil(); }
  64. template<typename Arg1,typename Arg2,typename Arg3>
  65. nil operator()( Arg1 const&, Arg2 const&, Arg3 const& )
  66. { report_access_to_invalid_parameter(); return nil(); }
  67. // Visitation support
  68. template<typename Visitor>
  69. void apply_to( Visitor& V ) const {}
  70. static nil& inst() { static nil s_inst; return s_inst; }
  71. private:
  72. nil() {}
  73. };
  74. // ************************************************************************** //
  75. // ************** named_parameter_base ************** //
  76. // ************************************************************************** //
  77. template<typename Derived>
  78. struct named_parameter_base {
  79. template<typename NP>
  80. named_parameter_combine<NP,Derived>
  81. operator,( NP const& np ) const { return named_parameter_combine<NP,Derived>( np, *static_cast<Derived const*>(this) ); }
  82. };
  83. //____________________________________________________________________________//
  84. // ************************************************************************** //
  85. // ************** named_parameter_combine ************** //
  86. // ************************************************************************** //
  87. template<typename NP, typename Rest = nil>
  88. struct named_parameter_combine
  89. : Rest
  90. , named_parameter_base<named_parameter_combine<NP,Rest> > {
  91. typedef typename NP::ref_type res_type;
  92. typedef named_parameter_combine<NP,Rest> self_type;
  93. // Constructor
  94. named_parameter_combine( NP const& np, Rest const& r )
  95. : Rest( r )
  96. , m_param( np )
  97. {}
  98. // Access methods
  99. res_type operator[]( keyword<typename NP::id,true> kw ) const { return m_param[kw]; }
  100. res_type operator[]( keyword<typename NP::id,false> kw ) const { return m_param[kw]; }
  101. using Rest::operator[];
  102. bool has( keyword<typename NP::id,false> kw ) const { return m_param.has( kw ); }
  103. using Rest::has;
  104. void erase( keyword<typename NP::id,false> kw ) const { m_param.erase( kw ); }
  105. using Rest::erase;
  106. #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) || \
  107. BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0610))
  108. template<typename NP>
  109. named_parameter_combine<NP,self_type> operator,( NP const& np ) const
  110. { return named_parameter_combine<NP,self_type>( np, *this ); }
  111. #else
  112. using named_parameter_base<named_parameter_combine<NP,Rest> >::operator,;
  113. #endif
  114. // Visitation support
  115. template<typename Visitor>
  116. void apply_to( Visitor& V ) const
  117. {
  118. m_param.apply_to( V );
  119. Rest::apply_to( V );
  120. }
  121. private:
  122. // Data members
  123. NP m_param;
  124. };
  125. } // namespace nfp_detail
  126. // ************************************************************************** //
  127. // ************** named_parameter ************** //
  128. // ************************************************************************** //
  129. template<typename T, typename unique_id,typename ReferenceType=T&>
  130. struct named_parameter
  131. : nfp_detail::named_parameter_base<named_parameter<T, unique_id,ReferenceType> >
  132. {
  133. typedef nfp_detail::nil nil_t;
  134. typedef T data_type;
  135. typedef ReferenceType ref_type;
  136. typedef unique_id id;
  137. // Constructor
  138. explicit named_parameter( ref_type v )
  139. : m_value( v )
  140. , m_erased( false )
  141. {}
  142. named_parameter( named_parameter const& np )
  143. : m_value( np.m_value )
  144. , m_erased( np.m_erased )
  145. {}
  146. // Access methods
  147. ref_type operator[]( keyword<unique_id,true> ) const { return m_erased ? nil_t::inst().template any_cast<ref_type>() : m_value; }
  148. ref_type operator[]( keyword<unique_id,false> ) const { return m_erased ? nil_t::inst().template any_cast<ref_type>() : m_value; }
  149. template<typename UnknownId>
  150. nil_t operator[]( keyword<UnknownId,false> ) const { return nil_t::inst(); }
  151. bool has( keyword<unique_id,false> ) const { return !m_erased; }
  152. template<typename UnknownId>
  153. bool has( keyword<UnknownId,false> ) const { return false; }
  154. void erase( keyword<unique_id,false> ) const { m_erased = true; }
  155. template<typename UnknownId>
  156. void erase( keyword<UnknownId,false> ) const {}
  157. // Visitation support
  158. template<typename Visitor>
  159. void apply_to( Visitor& V ) const
  160. {
  161. V.set_parameter( rtti::type_id<unique_id>(), m_value );
  162. }
  163. private:
  164. // Data members
  165. ref_type m_value;
  166. mutable bool m_erased;
  167. };
  168. //____________________________________________________________________________//
  169. // ************************************************************************** //
  170. // ************** no_params ************** //
  171. // ************************************************************************** //
  172. namespace nfp_detail {
  173. typedef named_parameter<char, struct no_params_type_t,char> no_params_type;
  174. } // namespace nfp_detail
  175. namespace {
  176. nfp_detail::no_params_type no_params( '\0' );
  177. } // local namespace
  178. //____________________________________________________________________________//
  179. // ************************************************************************** //
  180. // ************** keyword ************** //
  181. // ************************************************************************** //
  182. template<typename unique_id, bool required = false>
  183. struct keyword {
  184. typedef unique_id id;
  185. template<typename T>
  186. named_parameter<T const,unique_id>
  187. operator=( T const& t ) const { return named_parameter<T const,unique_id>( t ); }
  188. template<typename T>
  189. named_parameter<T,unique_id>
  190. operator=( T& t ) const { return named_parameter<T,unique_id>( t ); }
  191. named_parameter<char const*,unique_id,char const*>
  192. operator=( char const* t ) const { return named_parameter<char const*,unique_id,char const*>( t ); }
  193. };
  194. //____________________________________________________________________________//
  195. // ************************************************************************** //
  196. // ************** typed_keyword ************** //
  197. // ************************************************************************** //
  198. template<typename T, typename unique_id, bool required = false>
  199. struct typed_keyword : keyword<unique_id,required> {
  200. named_parameter<T const,unique_id>
  201. operator=( T const& t ) const { return named_parameter<T const,unique_id>( t ); }
  202. named_parameter<T,unique_id>
  203. operator=( T& t ) const { return named_parameter<T,unique_id>( t ); }
  204. };
  205. //____________________________________________________________________________//
  206. template<typename unique_id>
  207. struct typed_keyword<bool,unique_id,false>
  208. : keyword<unique_id,false>
  209. , named_parameter<bool,unique_id,bool> {
  210. typedef unique_id id;
  211. typed_keyword() : named_parameter<bool,unique_id,bool>( true ) {}
  212. named_parameter<bool,unique_id,bool>
  213. operator!() const { return named_parameter<bool,unique_id,bool>( false ); }
  214. };
  215. //____________________________________________________________________________//
  216. // ************************************************************************** //
  217. // ************** optionally_assign ************** //
  218. // ************************************************************************** //
  219. template<typename T>
  220. inline void
  221. optionally_assign( T&, nfp_detail::nil )
  222. {
  223. nfp_detail::report_access_to_invalid_parameter();
  224. }
  225. //____________________________________________________________________________//
  226. template<typename T, typename Source>
  227. inline void
  228. #if BOOST_WORKAROUND( __MWERKS__, BOOST_TESTED_AT( 0x3003 ) ) \
  229. || BOOST_WORKAROUND( __DECCXX_VER, BOOST_TESTED_AT(60590042) )
  230. optionally_assign( T& target, Source src )
  231. #else
  232. optionally_assign( T& target, Source const& src )
  233. #endif
  234. {
  235. using namespace unit_test;
  236. assign_op( target, src, static_cast<int>(0) );
  237. }
  238. //____________________________________________________________________________//
  239. template<typename T, typename Params, typename Keyword>
  240. inline void
  241. optionally_assign( T& target, Params const& p, Keyword k )
  242. {
  243. if( p.has(k) )
  244. optionally_assign( target, p[k] );
  245. }
  246. //____________________________________________________________________________//
  247. } // namespace nfp
  248. } // namespace boost
  249. #include <boost/test/detail/enable_warnings.hpp>
  250. #endif // BOOST_TEST_NAMED_PARAM_022505GER