Home | History | Annotate | Download | only in utils
      1 //  (C) Copyright Gennadiy Rozental 2001-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 
      6 //  See http://www.boost.org/libs/test for the library home page.
      7 //
      8 //  File        : $RCSfile$
      9 //
     10 //  Version     : $Revision: 54633 $
     11 //
     12 //  Description : simple facility that mimmic notion of read-only read-write
     13 //  properties in C++ classes. Original idea by Henrik Ravn.
     14 // ***************************************************************************
     15 
     16 #ifndef BOOST_TEST_CLASS_PROPERTIES_HPP_071894GER
     17 #define BOOST_TEST_CLASS_PROPERTIES_HPP_071894GER
     18 
     19 // Boost.Test
     20 #include <boost/test/detail/config.hpp>
     21 
     22 // Boost
     23 #if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))
     24 #include <boost/preprocessor/seq/for_each.hpp>
     25 #endif
     26 #include <boost/call_traits.hpp>
     27 #include <boost/type_traits/add_pointer.hpp>
     28 #include <boost/type_traits/add_const.hpp>
     29 #include <boost/utility/addressof.hpp>
     30 
     31 // STL
     32 #include <iosfwd>
     33 
     34 #include <boost/test/detail/suppress_warnings.hpp>
     35 
     36 //____________________________________________________________________________//
     37 
     38 namespace boost {
     39 
     40 namespace unit_test {
     41 
     42 // ************************************************************************** //
     43 // **************                 class_property               ************** //
     44 // ************************************************************************** //
     45 
     46 template<class PropertyType>
     47 class class_property {
     48 protected:
     49     typedef typename call_traits<PropertyType>::const_reference     read_access_t;
     50     typedef typename call_traits<PropertyType>::param_type          write_param_t;
     51     typedef typename add_pointer<typename add_const<PropertyType>::type>::type address_res_t;
     52 public:
     53     // Constructor
     54                     class_property() : value( PropertyType() ) {}
     55     explicit        class_property( write_param_t init_value )
     56     : value( init_value ) {}
     57 
     58     // Access methods
     59     operator        read_access_t() const   { return value; }
     60     read_access_t   get() const             { return value; }
     61     bool            operator!() const       { return !value; }
     62     address_res_t   operator&() const       { return &value; }
     63 
     64     // Data members
     65 #ifndef BOOST_TEST_NO_PROTECTED_USING
     66 protected:
     67 #endif
     68     PropertyType        value;
     69 };
     70 
     71 //____________________________________________________________________________//
     72 
     73 #ifdef BOOST_CLASSIC_IOSTREAMS
     74 
     75 template<class PropertyType>
     76 inline std::ostream&
     77 operator<<( std::ostream& os, class_property<PropertyType> const& p )
     78 
     79 #else
     80 
     81 template<typename CharT1, typename Tr,class PropertyType>
     82 inline std::basic_ostream<CharT1,Tr>&
     83 operator<<( std::basic_ostream<CharT1,Tr>& os, class_property<PropertyType> const& p )
     84 
     85 #endif
     86 {
     87     return os << p.get();
     88 }
     89 
     90 //____________________________________________________________________________//
     91 
     92 #define DEFINE_PROPERTY_FREE_BINARY_OPERATOR( op )                              \
     93 template<class PropertyType>                                                    \
     94 inline bool                                                                     \
     95 operator op( PropertyType const& lhs, class_property<PropertyType> const& rhs ) \
     96 {                                                                               \
     97     return lhs op rhs.get();                                                    \
     98 }                                                                               \
     99 template<class PropertyType>                                                    \
    100 inline bool                                                                     \
    101 operator op( class_property<PropertyType> const& lhs, PropertyType const& rhs ) \
    102 {                                                                               \
    103     return lhs.get() op rhs;                                                    \
    104 }                                                                               \
    105 template<class PropertyType>                                                    \
    106 inline bool                                                                     \
    107 operator op( class_property<PropertyType> const& lhs,                           \
    108              class_property<PropertyType> const& rhs )                          \
    109 {                                                                               \
    110     return lhs.get() op rhs.get();                                              \
    111 }                                                                               \
    112 /**/
    113 
    114 DEFINE_PROPERTY_FREE_BINARY_OPERATOR( == )
    115 DEFINE_PROPERTY_FREE_BINARY_OPERATOR( != )
    116 
    117 #undef DEFINE_PROPERTY_FREE_BINARY_OPERATOR
    118 
    119 #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
    120 
    121 #define DEFINE_PROPERTY_LOGICAL_OPERATOR( op )                                  \
    122 template<class PropertyType>                                                    \
    123 inline bool                                                                     \
    124 operator op( bool b, class_property<PropertyType> const& p )                    \
    125 {                                                                               \
    126     return b op p.get();                                                        \
    127 }                                                                               \
    128 template<class PropertyType>                                                    \
    129 inline bool                                                                     \
    130 operator op( class_property<PropertyType> const& p, bool b )                    \
    131 {                                                                               \
    132     return b op p.get();                                                        \
    133 }                                                                               \
    134 /**/
    135 
    136 DEFINE_PROPERTY_LOGICAL_OPERATOR( && )
    137 DEFINE_PROPERTY_LOGICAL_OPERATOR( || )
    138 
    139 #endif
    140 
    141 // ************************************************************************** //
    142 // **************               readonly_property              ************** //
    143 // ************************************************************************** //
    144 
    145 template<class PropertyType>
    146 class readonly_property : public class_property<PropertyType> {
    147     typedef class_property<PropertyType>         base_prop;
    148     typedef typename base_prop::address_res_t    arrow_res_t;
    149 protected:
    150     typedef typename base_prop::write_param_t    write_param_t;
    151 public:
    152     // Constructor
    153                     readonly_property() {}
    154     explicit        readonly_property( write_param_t init_value ) : base_prop( init_value ) {}
    155 
    156     // access methods
    157     arrow_res_t     operator->() const      { return boost::addressof( base_prop::value ); }
    158 };
    159 
    160 //____________________________________________________________________________//
    161 
    162 #if BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))
    163 
    164 #define BOOST_READONLY_PROPERTY( property_type, friends ) boost::unit_test::readwrite_property<property_type >
    165 
    166 #else
    167 
    168 #define BOOST_READONLY_PROPERTY_DECLARE_FRIEND(r, data, elem) friend class elem;
    169 
    170 #define BOOST_READONLY_PROPERTY( property_type, friends )                           \
    171 class BOOST_JOIN( readonly_property, __LINE__ )                                     \
    172 : public boost::unit_test::readonly_property<property_type > {                      \
    173     typedef boost::unit_test::readonly_property<property_type > base_prop;          \
    174     BOOST_PP_SEQ_FOR_EACH( BOOST_READONLY_PROPERTY_DECLARE_FRIEND, ' ', friends )   \
    175     typedef base_prop::write_param_t  write_param_t;                                \
    176 public:                                                                             \
    177                 BOOST_JOIN( readonly_property, __LINE__ )() {}                      \
    178     explicit    BOOST_JOIN( readonly_property, __LINE__ )( write_param_t init_v  )  \
    179     : base_prop( init_v ) {}                                                        \
    180 }                                                                                   \
    181 /**/
    182 
    183 #endif
    184 
    185 // ************************************************************************** //
    186 // **************              readwrite_property              ************** //
    187 // ************************************************************************** //
    188 
    189 template<class PropertyType>
    190 class readwrite_property : public class_property<PropertyType> {
    191     typedef class_property<PropertyType>                base_prop;
    192     typedef typename add_pointer<PropertyType>::type    arrow_res_t;
    193     typedef typename base_prop::address_res_t           const_arrow_res_t;
    194     typedef typename base_prop::write_param_t           write_param_t;
    195 public:
    196                     readwrite_property() : base_prop() {}
    197     explicit        readwrite_property( write_param_t init_value ) : base_prop( init_value ) {}
    198 
    199     // access methods
    200     void            set( write_param_t v )  { base_prop::value = v; }
    201     arrow_res_t     operator->()            { return boost::addressof( base_prop::value ); }
    202     const_arrow_res_t operator->() const    { return boost::addressof( base_prop::value ); }
    203 
    204 #ifndef BOOST_TEST_NO_PROTECTED_USING
    205     using           base_prop::value;
    206 #endif
    207 };
    208 
    209 //____________________________________________________________________________//
    210 
    211 } // unit_test
    212 
    213 } // namespace boost
    214 
    215 //____________________________________________________________________________//
    216 
    217 #include <boost/test/detail/enable_warnings.hpp>
    218 
    219 #undef BOOST_TEST_NO_PROTECTED_USING
    220 
    221 #endif // BOOST_TEST_CLASS_PROPERTIES_HPP_071894GER
    222