Home | History | Annotate | Download | only in mpl
      1 
      2 #ifndef BOOST_MPL_ASSERT_HPP_INCLUDED
      3 #define BOOST_MPL_ASSERT_HPP_INCLUDED
      4 
      5 // Copyright Aleksey Gurtovoy 2000-2006
      6 //
      7 // Distributed under the Boost Software License, Version 1.0.
      8 // (See accompanying file LICENSE_1_0.txt or copy at
      9 // http://www.boost.org/LICENSE_1_0.txt)
     10 //
     11 // See http://www.boost.org/libs/mpl for documentation.
     12 
     13 // $Id: assert.hpp 49267 2008-10-11 06:19:02Z agurtovoy $
     14 // $Date: 2008-10-10 23:19:02 -0700 (Fri, 10 Oct 2008) $
     15 // $Revision: 49267 $
     16 
     17 #include <boost/mpl/not.hpp>
     18 #include <boost/mpl/aux_/value_wknd.hpp>
     19 #include <boost/mpl/aux_/nested_type_wknd.hpp>
     20 #include <boost/mpl/aux_/yes_no.hpp>
     21 #include <boost/mpl/aux_/na.hpp>
     22 #include <boost/mpl/aux_/adl_barrier.hpp>
     23 
     24 #include <boost/mpl/aux_/config/nttp.hpp>
     25 #include <boost/mpl/aux_/config/dtp.hpp>
     26 #include <boost/mpl/aux_/config/gcc.hpp>
     27 #include <boost/mpl/aux_/config/msvc.hpp>
     28 #include <boost/mpl/aux_/config/static_constant.hpp>
     29 #include <boost/mpl/aux_/config/pp_counter.hpp>
     30 #include <boost/mpl/aux_/config/workaround.hpp>
     31 
     32 #include <boost/preprocessor/cat.hpp>
     33 
     34 #include <boost/config.hpp> // make sure 'size_t' is placed into 'std'
     35 #include <cstddef>
     36 
     37 
     38 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) \
     39     || (BOOST_MPL_CFG_GCC != 0) \
     40     || BOOST_WORKAROUND(__IBMCPP__, <= 600)
     41 #   define BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES
     42 #endif
     43 
     44 #if BOOST_WORKAROUND(__MWERKS__, < 0x3202) \
     45     || BOOST_WORKAROUND(__EDG_VERSION__, <= 238) \
     46     || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) \
     47     || BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840))
     48 #   define BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER
     49 #endif
     50 
     51 // agurt, 10/nov/06: use enums for Borland (which cannot cope with static constants)
     52 // and GCC (which issues "unused variable" warnings when static constants are used
     53 // at a function scope)
     54 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) \
     55     || (BOOST_MPL_CFG_GCC != 0)
     56 #   define BOOST_MPL_AUX_ASSERT_CONSTANT(T, expr) enum { expr }
     57 #else
     58 #   define BOOST_MPL_AUX_ASSERT_CONSTANT(T, expr) BOOST_STATIC_CONSTANT(T, expr)
     59 #endif
     60 
     61 
     62 BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
     63 
     64 struct failed {};
     65 
     66 // agurt, 24/aug/04: MSVC 7.1 workaround here and below: return/accept
     67 // 'assert<false>' by reference; can't apply it unconditionally -- apparently it
     68 // degrades the quality of GCC diagnostics
     69 #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
     70 #   define AUX778076_ASSERT_ARG(x) x&
     71 #else
     72 #   define AUX778076_ASSERT_ARG(x) x
     73 #endif
     74 
     75 template< bool C >  struct assert        { typedef void* type; };
     76 template<>          struct assert<false> { typedef AUX778076_ASSERT_ARG(assert) type; };
     77 
     78 template< bool C >
     79 int assertion_failed( typename assert<C>::type );
     80 
     81 template< bool C >
     82 struct assertion
     83 {
     84     static int failed( assert<false> );
     85 };
     86 
     87 template<>
     88 struct assertion<true>
     89 {
     90     static int failed( void* );
     91 };
     92 
     93 struct assert_
     94 {
     95 #if !defined(BOOST_MPL_CFG_NO_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES)
     96     template< typename T1, typename T2 = na, typename T3 = na, typename T4 = na > struct types {};
     97 #endif
     98     static assert_ const arg;
     99     enum relations { equal = 1, not_equal, greater, greater_equal, less, less_equal };
    100 };
    101 
    102 
    103 #if !defined(BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES)
    104 
    105 bool operator==( failed, failed );
    106 bool operator!=( failed, failed );
    107 bool operator>( failed, failed );
    108 bool operator>=( failed, failed );
    109 bool operator<( failed, failed );
    110 bool operator<=( failed, failed );
    111 
    112 #if defined(__EDG_VERSION__)
    113 template< bool (*)(failed, failed), long x, long y > struct assert_relation {};
    114 #   define BOOST_MPL_AUX_ASSERT_RELATION(x, y, r) assert_relation<r,x,y>
    115 #else
    116 template< BOOST_MPL_AUX_NTTP_DECL(long, x), BOOST_MPL_AUX_NTTP_DECL(long, y), bool (*)(failed, failed) >
    117 struct assert_relation {};
    118 #   define BOOST_MPL_AUX_ASSERT_RELATION(x, y, r) assert_relation<x,y,r>
    119 #endif
    120 
    121 #else // BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES
    122 
    123 boost::mpl::aux::weighted_tag<1>::type operator==( assert_, assert_ );
    124 boost::mpl::aux::weighted_tag<2>::type operator!=( assert_, assert_ );
    125 boost::mpl::aux::weighted_tag<3>::type operator>(  assert_, assert_ );
    126 boost::mpl::aux::weighted_tag<4>::type operator>=( assert_, assert_ );
    127 boost::mpl::aux::weighted_tag<5>::type operator<( assert_, assert_ );
    128 boost::mpl::aux::weighted_tag<6>::type operator<=( assert_, assert_ );
    129 
    130 template< assert_::relations r, long x, long y > struct assert_relation {};
    131 
    132 #endif
    133 
    134 
    135 #if !defined(BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER)
    136 
    137 template< bool > struct assert_arg_pred_impl { typedef int type; };
    138 template<> struct assert_arg_pred_impl<true> { typedef void* type; };
    139 
    140 template< typename P > struct assert_arg_pred
    141 {
    142     typedef typename P::type p_type;
    143     typedef typename assert_arg_pred_impl< p_type::value >::type type;
    144 };
    145 
    146 template< typename P > struct assert_arg_pred_not
    147 {
    148     typedef typename P::type p_type;
    149     BOOST_MPL_AUX_ASSERT_CONSTANT( bool, p = !p_type::value );
    150     typedef typename assert_arg_pred_impl<p>::type type;
    151 };
    152 
    153 template< typename Pred >
    154 failed ************ (Pred::************
    155       assert_arg( void (*)(Pred), typename assert_arg_pred<Pred>::type )
    156     );
    157 
    158 template< typename Pred >
    159 failed ************ (boost::mpl::not_<Pred>::************
    160       assert_not_arg( void (*)(Pred), typename assert_arg_pred_not<Pred>::type )
    161     );
    162 
    163 template< typename Pred >
    164 AUX778076_ASSERT_ARG(assert<false>)
    165 assert_arg( void (*)(Pred), typename assert_arg_pred_not<Pred>::type );
    166 
    167 template< typename Pred >
    168 AUX778076_ASSERT_ARG(assert<false>)
    169 assert_not_arg( void (*)(Pred), typename assert_arg_pred<Pred>::type );
    170 
    171 
    172 #else // BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER
    173 
    174 template< bool c, typename Pred > struct assert_arg_type_impl
    175 {
    176     typedef failed      ************ Pred::* mwcw83_wknd;
    177     typedef mwcw83_wknd ************* type;
    178 };
    179 
    180 template< typename Pred > struct assert_arg_type_impl<true,Pred>
    181 {
    182     typedef AUX778076_ASSERT_ARG(assert<false>) type;
    183 };
    184 
    185 template< typename Pred > struct assert_arg_type
    186     : assert_arg_type_impl< BOOST_MPL_AUX_VALUE_WKND(BOOST_MPL_AUX_NESTED_TYPE_WKND(Pred))::value, Pred >
    187 {
    188 };
    189 
    190 template< typename Pred >
    191 typename assert_arg_type<Pred>::type
    192 assert_arg(void (*)(Pred), int);
    193 
    194 template< typename Pred >
    195 typename assert_arg_type< boost::mpl::not_<Pred> >::type
    196 assert_not_arg(void (*)(Pred), int);
    197 
    198 #   if !defined(BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES)
    199 template< long x, long y, bool (*r)(failed, failed) >
    200 typename assert_arg_type_impl< false,BOOST_MPL_AUX_ASSERT_RELATION(x,y,r) >::type
    201 assert_rel_arg( BOOST_MPL_AUX_ASSERT_RELATION(x,y,r) );
    202 #   else
    203 template< assert_::relations r, long x, long y >
    204 typename assert_arg_type_impl< false,assert_relation<r,x,y> >::type
    205 assert_rel_arg( assert_relation<r,x,y> );
    206 #   endif
    207 
    208 #endif // BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER
    209 
    210 #undef AUX778076_ASSERT_ARG
    211 
    212 BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
    213 
    214 
    215 // BOOST_MPL_ASSERT((pred<x,...>))
    216 
    217 #define BOOST_MPL_ASSERT(pred) \
    218 BOOST_MPL_AUX_ASSERT_CONSTANT( \
    219       std::size_t \
    220     , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \
    221           boost::mpl::assertion_failed<false>( \
    222               boost::mpl::assert_arg( (void (*) pred)0, 1 ) \
    223             ) \
    224         ) \
    225     ) \
    226 /**/
    227 
    228 // BOOST_MPL_ASSERT_NOT((pred<x,...>))
    229 
    230 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
    231 #   define BOOST_MPL_ASSERT_NOT(pred) \
    232 enum { \
    233       BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \
    234           boost::mpl::assertion<false>::failed( \
    235               boost::mpl::assert_not_arg( (void (*) pred)0, 1 ) \
    236             ) \
    237         ) \
    238 }\
    239 /**/
    240 #else
    241 #   define BOOST_MPL_ASSERT_NOT(pred) \
    242 BOOST_MPL_AUX_ASSERT_CONSTANT( \
    243       std::size_t \
    244     , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \
    245           boost::mpl::assertion_failed<false>( \
    246               boost::mpl::assert_not_arg( (void (*) pred)0, 1 ) \
    247             ) \
    248         ) \
    249    ) \
    250 /**/
    251 #endif
    252 
    253 // BOOST_MPL_ASSERT_RELATION(x, ==|!=|<=|<|>=|>, y)
    254 
    255 #if defined(BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES)
    256 
    257 #   if !defined(BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER)
    258 // agurt, 9/nov/06: 'enum' below is a workaround for gcc 4.0.4/4.1.1 bugs #29522 and #29518
    259 #   define BOOST_MPL_ASSERT_RELATION_IMPL(counter, x, rel, y)      \
    260 enum { BOOST_PP_CAT(mpl_assert_rel_value,counter) = (x rel y) }; \
    261 BOOST_MPL_AUX_ASSERT_CONSTANT( \
    262       std::size_t \
    263     , BOOST_PP_CAT(mpl_assertion_in_line_,counter) = sizeof( \
    264         boost::mpl::assertion_failed<BOOST_PP_CAT(mpl_assert_rel_value,counter)>( \
    265             (boost::mpl::failed ************ ( boost::mpl::assert_relation< \
    266                   boost::mpl::assert_::relations( sizeof( \
    267                       boost::mpl::assert_::arg rel boost::mpl::assert_::arg \
    268                     ) ) \
    269                 , x \
    270                 , y \
    271                 >::************)) 0 ) \
    272         ) \
    273     ) \
    274 /**/
    275 #   else
    276 #   define BOOST_MPL_ASSERT_RELATION_IMPL(counter, x, rel, y)    \
    277 BOOST_MPL_AUX_ASSERT_CONSTANT( \
    278       std::size_t \
    279     , BOOST_PP_CAT(mpl_assert_rel,counter) = sizeof( \
    280           boost::mpl::assert_::arg rel boost::mpl::assert_::arg \
    281         ) \
    282     ); \
    283 BOOST_MPL_AUX_ASSERT_CONSTANT( bool, BOOST_PP_CAT(mpl_assert_rel_value,counter) = (x rel y) ); \
    284 BOOST_MPL_AUX_ASSERT_CONSTANT( \
    285       std::size_t \
    286     , BOOST_PP_CAT(mpl_assertion_in_line_,counter) = sizeof( \
    287         boost::mpl::assertion_failed<BOOST_PP_CAT(mpl_assert_rel_value,counter)>( \
    288               boost::mpl::assert_rel_arg( boost::mpl::assert_relation< \
    289                   boost::mpl::assert_::relations(BOOST_PP_CAT(mpl_assert_rel,counter)) \
    290                 , x \
    291                 , y \
    292                 >() ) \
    293             ) \
    294         ) \
    295     ) \
    296 /**/
    297 #   endif
    298 
    299 #   define BOOST_MPL_ASSERT_RELATION(x, rel, y) \
    300 BOOST_MPL_ASSERT_RELATION_IMPL(BOOST_MPL_AUX_PP_COUNTER(), x, rel, y) \
    301 /**/
    302 
    303 #else // !BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES
    304 
    305 #   if defined(BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER)
    306 #   define BOOST_MPL_ASSERT_RELATION(x, rel, y) \
    307 BOOST_MPL_AUX_ASSERT_CONSTANT( \
    308       std::size_t \
    309     , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \
    310         boost::mpl::assertion_failed<(x rel y)>( boost::mpl::assert_rel_arg( \
    311               boost::mpl::BOOST_MPL_AUX_ASSERT_RELATION(x,y,(&boost::mpl::operator rel))() \
    312             ) ) \
    313         ) \
    314     ) \
    315 /**/
    316 #   else
    317 #   define BOOST_MPL_ASSERT_RELATION(x, rel, y) \
    318 BOOST_MPL_AUX_ASSERT_CONSTANT( \
    319       std::size_t \
    320     , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \
    321         boost::mpl::assertion_failed<(x rel y)>( (boost::mpl::failed ************ ( \
    322             boost::mpl::BOOST_MPL_AUX_ASSERT_RELATION(x,y,(&boost::mpl::operator rel))::************))0 ) \
    323         ) \
    324     ) \
    325 /**/
    326 #   endif
    327 
    328 #endif
    329 
    330 
    331 // BOOST_MPL_ASSERT_MSG( (pred<x,...>::value), USER_PROVIDED_MESSAGE, (types<x,...>) )
    332 
    333 #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3202))
    334 #   define BOOST_MPL_ASSERT_MSG_IMPL( counter, c, msg, types_ ) \
    335 struct msg; \
    336 typedef struct BOOST_PP_CAT(msg,counter) : boost::mpl::assert_ \
    337 { \
    338     using boost::mpl::assert_::types; \
    339     static boost::mpl::failed ************ (msg::************ assert_arg()) types_ \
    340     { return 0; } \
    341 } BOOST_PP_CAT(mpl_assert_arg,counter); \
    342 BOOST_MPL_AUX_ASSERT_CONSTANT( \
    343       std::size_t \
    344     , BOOST_PP_CAT(mpl_assertion_in_line_,counter) = sizeof( \
    345         boost::mpl::assertion<(c)>::failed( BOOST_PP_CAT(mpl_assert_arg,counter)::assert_arg() ) \
    346         ) \
    347     ) \
    348 /**/
    349 #else
    350 #   define BOOST_MPL_ASSERT_MSG_IMPL( counter, c, msg, types_ )  \
    351 struct msg; \
    352 typedef struct BOOST_PP_CAT(msg,counter) : boost::mpl::assert_ \
    353 { \
    354     static boost::mpl::failed ************ (msg::************ assert_arg()) types_ \
    355     { return 0; } \
    356 } BOOST_PP_CAT(mpl_assert_arg,counter); \
    357 BOOST_MPL_AUX_ASSERT_CONSTANT( \
    358       std::size_t \
    359     , BOOST_PP_CAT(mpl_assertion_in_line_,counter) = sizeof( \
    360         boost::mpl::assertion_failed<(c)>( BOOST_PP_CAT(mpl_assert_arg,counter)::assert_arg() ) \
    361         ) \
    362     ) \
    363 /**/
    364 #endif
    365 
    366 #define BOOST_MPL_ASSERT_MSG( c, msg, types_ ) \
    367 BOOST_MPL_ASSERT_MSG_IMPL( BOOST_MPL_AUX_PP_COUNTER(), c, msg, types_ ) \
    368 /**/
    369 
    370 #endif // BOOST_MPL_ASSERT_HPP_INCLUDED
    371