Advertisement
Guest User

hito

a guest
Sep 20th, 2008
457
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.20 KB | None | 0 0
  1. #ifndef HITO_REF
  2. #define HITO_REF
  3.  
  4. #include <boost/type_traits/is_base_of.hpp>
  5. #include <boost/type_traits/integral_constant.hpp>
  6. #include <boost/mpl/has_xxx.hpp>
  7.  
  8.  
  9. namespace hito {
  10.  
  11. namespace detail {
  12.  
  13. // this macro generates a metafunction has_result_type<T>.
  14. // it returns true if T has nested type name T::result_type.
  15. // otherwise, it returns false.
  16. BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
  17.  
  18.  
  19. typedef char yes_type ;
  20. struct no_type { char padding[8] ; } ;
  21.  
  22.  
  23. template < typename T >
  24. struct is_base_of_unary_function_impl
  25. {
  26.         template < typename R, typename T1 >
  27.         static yes_type check( const volatile std::unary_function<T1, R> * ) ;
  28.        
  29.         static no_type check( const volatile void * ) ;
  30.        
  31.         static const bool value = sizeof( check( static_cast< T * >(NULL) ) ) == sizeof( yes_type ) ;    
  32. } ;
  33.  
  34. template < typename T >
  35. struct is_base_of_binary_function_impl
  36. {
  37.         template < typename R, typename T1, typename T2 >
  38.         static yes_type check( const volatile std::binary_function<T1, T2, R> * ) ;
  39.        
  40.         static no_type check( const volatile void * ) ;
  41.        
  42.         static const bool value = sizeof( check( static_cast< T * >(NULL) ) ) == sizeof( yes_type ) ;    
  43. } ;
  44.  
  45.  
  46. // this metafunction returns true if T is derived from std::unary_function
  47. // otherwise, it returns false.
  48. template < typename T >
  49. struct is_base_of_unary_function
  50.         : boost::integral_constant< bool, is_base_of_unary_function_impl<T>::value >
  51. { } ;
  52.  
  53. // this metafunction returns true if T is derived from std::binary_function
  54. // otherwise, it returns false.
  55. template < typename T >
  56. struct is_base_of_binary_function
  57.         : boost::integral_constant< bool, is_base_of_binary_function_impl<T>::value >
  58. { } ;
  59.  
  60.  
  61. // if T has nested type name result_type.
  62. // because TR1 only mentions about result_type,
  63. // we couldn't use argument_types, and couldn't know if it is a unary function or binary function or both.
  64. template < typename Derived, typename T >
  65. struct generic_invocation
  66. {
  67.         typedef  typename T::result_type result_type ;
  68.         template < typename T1 >
  69.         result_type operator () ( T1 const & arg1 ) const
  70.         {
  71.                 Derived const & self = static_cast< Derived const & >( *this ) ;
  72.                 return self.get()( arg1 ) ;
  73.         }
  74.        
  75.         template < typename T1, typename T2 >
  76.         result_type operator () ( T1 const & arg1, T2 const & arg2 ) const
  77.         {
  78.                 Derived const & self = static_cast< Derived const & >( *this ) ;
  79.                 return self.get()( arg1, arg2 ) ;
  80.         }
  81. } ;
  82.  
  83. // make base class. avoid multiple inheritance if possible.
  84. template < typename Derived, typename T, bool is_unary, bool is_binary, bool has_result >
  85. struct make_invocation_base
  86. {
  87.  
  88. } ;
  89.  
  90. // if it has unary_function as base
  91. template < typename Derived, typename T, bool val >
  92. struct make_invocation_base< Derived, T, true, false, val >
  93.         : std::unary_function< typename T::argument_type, typename T::result_type >
  94. {
  95.         result_type operator () ( argument_type const & arg1 ) const
  96.         {
  97.                 Derived const & self = static_cast< Derived const & >( *this ) ;
  98.                 return self.get()( arg1 ) ;
  99.         }
  100.  
  101. } ;
  102.  
  103. // if it has binary_function as base
  104. template < typename Derived, typename T, bool val >
  105. struct make_invocation_base< Derived, T, false, true, val >
  106.         : std::binary_function< typename T::first_argument_type, typename T::second_argument_type, typename T::result_type >
  107. {
  108.         result_type operator () ( first_argument_type const & arg1, second_argument_type const & arg2 ) const
  109.         {
  110.                 Derived const & self = static_cast< Derived const & >( *this ) ;
  111.                 return self.get()( arg1, arg2 ) ;
  112.         }
  113.  
  114. } ;
  115.  
  116. // if it has both unary_function and binary_function as bases
  117. template < typename Derived, typename T, bool val >
  118. struct make_invocation_base< Derived, T, true, true, val >
  119.         : std::unary_function< typename T::argument_type, typename T::result_type >
  120.         , std::binary_function< typename T::first_argument_type, typename T::second_argument_type, typename T::result_type >
  121. {
  122.         typedef typename T::result_type result_type ;
  123.        
  124.         result_type operator () ( argument_type const & arg1 ) const
  125.         {
  126.                 Derived const & self = static_cast< Derived const & >( *this ) ;
  127.                 return self.get()( arg1 ) ;
  128.         }
  129.        
  130.         result_type operator () ( first_argument_type const & arg1, second_argument_type const & arg2 ) const
  131.         {
  132.                 Derived const & self = static_cast< Derived const & >( *this ) ;
  133.                 return self.get()( arg1, arg2 ) ;
  134.         }
  135.  
  136. } ;
  137.  
  138. // else if it has nested type name result_type
  139. template < typename Derived, typename T >
  140. struct make_invocation_base< Derived, T, false, false, true >
  141.         : generic_invocation< Derived, T >
  142. { } ;
  143.  
  144.  
  145. // Primary Template for reference_wrapper_invocation.
  146. // this class defines function call operator and inherites unary_function/binary_function or both.
  147. template < typename Derived, typename T >
  148. struct reference_wrapper_invocation
  149.         : make_invocation_base< Derived, T
  150.                 , is_base_of_unary_function< T >::value
  151.                 , is_base_of_binary_function< T >::value
  152.                 , has_result_type< T >::value
  153.           >
  154. { } ;
  155.  
  156. // unary function type
  157. template < typename Derived, typename R, typename T1 >
  158. struct reference_wrapper_invocation< Derived, R(T1) >
  159.         : std::unary_function< T1, R >
  160. {      
  161.         R operator() ( T1 const & arg1 ) const
  162.         {
  163.                 Derived const & self = static_cast< Derived const & >( *this ) ;
  164.                 return self.get()( arg1 ) ;
  165.         }
  166. } ;
  167.  
  168. // pointer to unary function type
  169. template < typename Derived, typename R, typename T1 >
  170. struct reference_wrapper_invocation< Derived, R(*)(T1) >
  171.         : std::unary_function< T1, R >
  172. {
  173.         R operator() ( T1 const & arg1 ) const
  174.         {
  175.                 Derived const & self = static_cast< Derived const & >( *this ) ;
  176.                 return self.get()( arg1 ) ;
  177.         }
  178. } ;
  179.  
  180. // pointer to nullary member function type
  181. template < typename Derived, typename R, typename T1 >
  182. struct reference_wrapper_invocation< Derived, R (T1::*)() >
  183.         : std::unary_function< T1, R >
  184. {
  185.         R operator() ( T1 & arg1 ) const
  186.         {
  187.                 Derived const & self = static_cast< Derived const & >( *this ) ;
  188.                 // call T1's member function by a pointer.
  189.                 return (arg1.*self.get())( ) ;
  190.         }
  191. } ;
  192.  
  193. // pointer to nullary member function type with const qualifier
  194. template < typename Derived, typename R, typename T1 >
  195. struct reference_wrapper_invocation< Derived, R (T1::*)() const >
  196.         : std::unary_function< T1, R >
  197. {
  198.         R operator() ( T1 & arg1 ) const
  199.         {
  200.                 Derived const & self = static_cast< Derived const & >( *this ) ;
  201.                 // call T1's member function by a pointer.
  202.                 return (arg1.*self.get())( ) ;
  203.         }
  204. } ;
  205.  
  206. // binary function type
  207. template < typename Derived, typename R, typename T1, typename T2 >
  208. struct reference_wrapper_invocation< Derived, R(T1, T2) >
  209.         : std::binary_function< T1, T2, R >
  210. {      
  211.         R operator() ( T1 const & arg1, T2 const & arg2 ) const
  212.         {
  213.                 Derived const & self = static_cast< Derived const & >( *this ) ;
  214.                 return self.get()( arg1, arg2 ) ;
  215.         }
  216. } ;
  217.  
  218. // pointer to binary function type
  219. template < typename Derived, typename R, typename T1, typename T2 >
  220. struct reference_wrapper_invocation< Derived, R(*)(T1, T2) >
  221.         : std::binary_function< T1, T2, R >
  222. {      
  223.         R operator() ( T1 const & arg1, T2 const & arg2 ) const
  224.         {
  225.                 Derived const & self = static_cast< Derived const & >( *this ) ;
  226.                 return self.get()( arg1, arg2 ) ;
  227.         }
  228. } ;
  229.  
  230. // pointer to urnary member function type
  231. template < typename Derived, typename R, typename T1, typename T2 >
  232. struct reference_wrapper_invocation< Derived, R (T1::*)( T2 ) >
  233.         : std::binary_function< T1, T2, R >
  234. {
  235.         R operator() ( T1 & arg1, T2 const & arg2 ) const
  236.         {
  237.                 Derived const & self = static_cast< Derived const & >( *this ) ;
  238.                 // call T1's member function by a pointer.
  239.                 return (arg1.*self.get())( arg2 ) ;
  240.         }
  241. } ;
  242.  
  243. // pointer to urnary member function type with const qualifier
  244. template < typename Derived, typename R, typename T1, typename T2 >
  245. struct reference_wrapper_invocation< Derived, R (T1::*)( T2 ) const >
  246.         : std::binary_function< T1, T2, R >
  247. {
  248.         R operator() ( T1 & arg1, T2 const & arg2 ) const
  249.         {
  250.                 Derived const & self = static_cast< Derived const & >( *this ) ;
  251.                 // call T1's member function by a pointer.
  252.                 return (arg1.*self.get())( arg2 ) ;
  253.         }
  254. } ;
  255.  
  256.  
  257. } // namespace detail
  258.  
  259. template < typename T >
  260. class reference_wrapper
  261.         : public detail::reference_wrapper_invocation< reference_wrapper< T >, T >
  262. {
  263. public :
  264.         typedef T type ;
  265.        
  266.         reference_wrapper( T & x )
  267.                 : object( x )
  268.         { }
  269.        
  270.         reference_wrapper( const reference_wrapper< T > & x )
  271.                 : object( x.get() )
  272.         { }
  273.        
  274.         operator T & () const
  275.         {
  276.                 return get() ;
  277.         }
  278.        
  279.        
  280.         T & get() const
  281.         {
  282.                 return object ;
  283.         }
  284.  
  285. private :
  286.         T & object ;
  287. } ;
  288.  
  289. // reference_wrapper helper functions
  290. template < typename T >
  291. reference_wrapper< T > ref( T & t )
  292. {
  293.         return reference_wrapper< T >( t ) ;
  294. }
  295.  
  296. template < typename T >
  297. reference_wrapper< T > ref( reference_wrapper< T > t )
  298. {
  299.         return ref( t.get() ) ;
  300. }
  301.  
  302. template < typename T >
  303. reference_wrapper< T const > cref( T const & t )
  304. {
  305.         return reference_wrapper< T const >( t ) ;
  306. }
  307.  
  308. template < typename T >
  309. reference_wrapper< T const > cref( reference_wrapper< T > t )
  310. {
  311.         return cref( t.get() ) ;
  312. }      
  313.  
  314.  
  315. } // namespace hito
  316.  
  317. #endif // #ifndef HITO_REF
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement