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$ 14 // $Date$ 15 // $Revision$ 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/gpu.hpp> 29 #include <boost/mpl/aux_/config/static_constant.hpp> 30 #include <boost/mpl/aux_/config/pp_counter.hpp> 31 #include <boost/mpl/aux_/config/workaround.hpp> 32 33 #include <boost/preprocessor/cat.hpp> 34 35 #include <boost/config.hpp> // make sure 'size_t' is placed into 'std' 36 #include <cstddef> 37 38 #if BOOST_WORKAROUND(BOOST_MSVC, == 1700) 39 #include <boost/mpl/if.hpp> 40 #endif 41 42 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) \ 43 || (BOOST_MPL_CFG_GCC != 0) \ 44 || BOOST_WORKAROUND(__IBMCPP__, <= 600) 45 # define BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES 46 #endif 47 48 #if BOOST_WORKAROUND(__MWERKS__, < 0x3202) \ 49 || BOOST_WORKAROUND(__EDG_VERSION__, <= 238) \ 50 || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) \ 51 || BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840)) 52 # define BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER 53 #endif 54 55 // agurt, 10/nov/06: use enums for Borland (which cannot cope with static constants) 56 // and GCC (which issues "unused variable" warnings when static constants are used 57 // at a function scope) 58 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) \ 59 || (BOOST_MPL_CFG_GCC != 0) || (BOOST_MPL_CFG_GPU != 0) 60 # define BOOST_MPL_AUX_ASSERT_CONSTANT(T, expr) enum { expr } 61 #else 62 # define BOOST_MPL_AUX_ASSERT_CONSTANT(T, expr) BOOST_STATIC_CONSTANT(T, expr) 63 #endif 64 65 66 BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN 67 68 struct failed {}; 69 70 // agurt, 24/aug/04: MSVC 7.1 workaround here and below: return/accept 71 // 'assert<false>' by reference; can't apply it unconditionally -- apparently it 72 // degrades the quality of GCC diagnostics 73 #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) 74 # define AUX778076_ASSERT_ARG(x) x& 75 #else 76 # define AUX778076_ASSERT_ARG(x) x 77 #endif 78 79 template< bool C > struct assert { typedef void* type; }; 80 template<> struct assert<false> { typedef AUX778076_ASSERT_ARG(assert) type; }; 81 82 template< bool C > 83 int assertion_failed( typename assert<C>::type ); 84 85 template< bool C > 86 struct assertion 87 { 88 static int failed( assert<false> ); 89 }; 90 91 template<> 92 struct assertion<true> 93 { 94 static int failed( void* ); 95 }; 96 97 struct assert_ 98 { 99 #if !defined(BOOST_MPL_CFG_NO_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES) 100 template< typename T1, typename T2 = na, typename T3 = na, typename T4 = na > struct types {}; 101 #endif 102 static assert_ const arg; 103 enum relations { equal = 1, not_equal, greater, greater_equal, less, less_equal }; 104 }; 105 106 107 #if !defined(BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES) 108 109 bool operator==( failed, failed ); 110 bool operator!=( failed, failed ); 111 bool operator>( failed, failed ); 112 bool operator>=( failed, failed ); 113 bool operator<( failed, failed ); 114 bool operator<=( failed, failed ); 115 116 #if defined(__EDG_VERSION__) 117 template< bool (*)(failed, failed), long x, long y > struct assert_relation {}; 118 # define BOOST_MPL_AUX_ASSERT_RELATION(x, y, r) assert_relation<r,x,y> 119 #else 120 template< BOOST_MPL_AUX_NTTP_DECL(long, x), BOOST_MPL_AUX_NTTP_DECL(long, y), bool (*)(failed, failed) > 121 struct assert_relation {}; 122 # define BOOST_MPL_AUX_ASSERT_RELATION(x, y, r) assert_relation<x,y,r> 123 #endif 124 125 #else // BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES 126 127 boost::mpl::aux::weighted_tag<1>::type operator==( assert_, assert_ ); 128 boost::mpl::aux::weighted_tag<2>::type operator!=( assert_, assert_ ); 129 boost::mpl::aux::weighted_tag<3>::type operator>( assert_, assert_ ); 130 boost::mpl::aux::weighted_tag<4>::type operator>=( assert_, assert_ ); 131 boost::mpl::aux::weighted_tag<5>::type operator<( assert_, assert_ ); 132 boost::mpl::aux::weighted_tag<6>::type operator<=( assert_, assert_ ); 133 134 template< assert_::relations r, long x, long y > struct assert_relation {}; 135 136 #endif 137 138 #if BOOST_WORKAROUND(BOOST_MSVC, == 1700) 139 140 template<class Pred> 141 struct extract_assert_pred; 142 143 template<class Pred> 144 struct extract_assert_pred<void(Pred)> { typedef Pred type; }; 145 146 template<class Pred> 147 struct eval_assert { 148 typedef typename extract_assert_pred<Pred>::type P; 149 typedef typename P::type p_type; 150 typedef typename ::boost::mpl::if_c<p_type::value, 151 AUX778076_ASSERT_ARG(assert<false>), 152 failed ************ P::************ 153 >::type type; 154 }; 155 156 template<class Pred> 157 struct eval_assert_not { 158 typedef typename extract_assert_pred<Pred>::type P; 159 typedef typename P::type p_type; 160 typedef typename ::boost::mpl::if_c<!p_type::value, 161 AUX778076_ASSERT_ARG(assert<false>), 162 failed ************ ::boost::mpl::not_<P>::************ 163 >::type type; 164 }; 165 166 template< typename T > 167 T make_assert_arg(); 168 169 #elif !defined(BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER) 170 171 template< bool > struct assert_arg_pred_impl { typedef int type; }; 172 template<> struct assert_arg_pred_impl<true> { typedef void* type; }; 173 174 template< typename P > struct assert_arg_pred 175 { 176 typedef typename P::type p_type; 177 typedef typename assert_arg_pred_impl< p_type::value >::type type; 178 }; 179 180 template< typename P > struct assert_arg_pred_not 181 { 182 typedef typename P::type p_type; 183 BOOST_MPL_AUX_ASSERT_CONSTANT( bool, p = !p_type::value ); 184 typedef typename assert_arg_pred_impl<p>::type type; 185 }; 186 187 template< typename Pred > 188 failed ************ (Pred::************ 189 assert_arg( void (*)(Pred), typename assert_arg_pred<Pred>::type ) 190 ); 191 192 template< typename Pred > 193 failed ************ (boost::mpl::not_<Pred>::************ 194 assert_not_arg( void (*)(Pred), typename assert_arg_pred_not<Pred>::type ) 195 ); 196 197 template< typename Pred > 198 AUX778076_ASSERT_ARG(assert<false>) 199 assert_arg( void (*)(Pred), typename assert_arg_pred_not<Pred>::type ); 200 201 template< typename Pred > 202 AUX778076_ASSERT_ARG(assert<false>) 203 assert_not_arg( void (*)(Pred), typename assert_arg_pred<Pred>::type ); 204 205 206 #else // BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER 207 208 template< bool c, typename Pred > struct assert_arg_type_impl 209 { 210 typedef failed ************ Pred::* mwcw83_wknd; 211 typedef mwcw83_wknd ************* type; 212 }; 213 214 template< typename Pred > struct assert_arg_type_impl<true,Pred> 215 { 216 typedef AUX778076_ASSERT_ARG(assert<false>) type; 217 }; 218 219 template< typename Pred > struct assert_arg_type 220 : assert_arg_type_impl< BOOST_MPL_AUX_VALUE_WKND(BOOST_MPL_AUX_NESTED_TYPE_WKND(Pred))::value, Pred > 221 { 222 }; 223 224 template< typename Pred > 225 typename assert_arg_type<Pred>::type 226 assert_arg(void (*)(Pred), int); 227 228 template< typename Pred > 229 typename assert_arg_type< boost::mpl::not_<Pred> >::type 230 assert_not_arg(void (*)(Pred), int); 231 232 # if !defined(BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES) 233 template< long x, long y, bool (*r)(failed, failed) > 234 typename assert_arg_type_impl< false,BOOST_MPL_AUX_ASSERT_RELATION(x,y,r) >::type 235 assert_rel_arg( BOOST_MPL_AUX_ASSERT_RELATION(x,y,r) ); 236 # else 237 template< assert_::relations r, long x, long y > 238 typename assert_arg_type_impl< false,assert_relation<r,x,y> >::type 239 assert_rel_arg( assert_relation<r,x,y> ); 240 # endif 241 242 #endif // BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER 243 244 #undef AUX778076_ASSERT_ARG 245 246 BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE 247 248 #if BOOST_WORKAROUND(BOOST_MSVC, == 1700) 249 250 // BOOST_MPL_ASSERT((pred<x,...>)) 251 252 #define BOOST_MPL_ASSERT(pred) \ 253 BOOST_MPL_AUX_ASSERT_CONSTANT( \ 254 std::size_t \ 255 , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \ 256 boost::mpl::assertion_failed<false>( \ 257 boost::mpl::make_assert_arg< \ 258 typename boost::mpl::eval_assert<void pred>::type \ 259 >() \ 260 ) \ 261 ) \ 262 ) \ 263 /**/ 264 265 // BOOST_MPL_ASSERT_NOT((pred<x,...>)) 266 267 #define BOOST_MPL_ASSERT_NOT(pred) \ 268 BOOST_MPL_AUX_ASSERT_CONSTANT( \ 269 std::size_t \ 270 , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \ 271 boost::mpl::assertion_failed<false>( \ 272 boost::mpl::make_assert_arg< \ 273 typename boost::mpl::eval_assert_not<void pred>::type \ 274 >() \ 275 ) \ 276 ) \ 277 ) \ 278 /**/ 279 280 #else 281 282 // BOOST_MPL_ASSERT((pred<x,...>)) 283 284 #define BOOST_MPL_ASSERT(pred) \ 285 BOOST_MPL_AUX_ASSERT_CONSTANT( \ 286 std::size_t \ 287 , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \ 288 boost::mpl::assertion_failed<false>( \ 289 boost::mpl::assert_arg( (void (*) pred)0, 1 ) \ 290 ) \ 291 ) \ 292 ) \ 293 /**/ 294 295 // BOOST_MPL_ASSERT_NOT((pred<x,...>)) 296 297 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) 298 # define BOOST_MPL_ASSERT_NOT(pred) \ 299 enum { \ 300 BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \ 301 boost::mpl::assertion<false>::failed( \ 302 boost::mpl::assert_not_arg( (void (*) pred)0, 1 ) \ 303 ) \ 304 ) \ 305 }\ 306 /**/ 307 #else 308 # define BOOST_MPL_ASSERT_NOT(pred) \ 309 BOOST_MPL_AUX_ASSERT_CONSTANT( \ 310 std::size_t \ 311 , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \ 312 boost::mpl::assertion_failed<false>( \ 313 boost::mpl::assert_not_arg( (void (*) pred)0, 1 ) \ 314 ) \ 315 ) \ 316 ) \ 317 /**/ 318 #endif 319 320 #endif 321 322 // BOOST_MPL_ASSERT_RELATION(x, ==|!=|<=|<|>=|>, y) 323 324 #if defined(BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES) 325 326 # if !defined(BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER) 327 // agurt, 9/nov/06: 'enum' below is a workaround for gcc 4.0.4/4.1.1 bugs #29522 and #29518 328 # define BOOST_MPL_ASSERT_RELATION_IMPL(counter, x, rel, y) \ 329 enum { BOOST_PP_CAT(mpl_assert_rel_value,counter) = (x rel y) }; \ 330 BOOST_MPL_AUX_ASSERT_CONSTANT( \ 331 std::size_t \ 332 , BOOST_PP_CAT(mpl_assertion_in_line_,counter) = sizeof( \ 333 boost::mpl::assertion_failed<BOOST_PP_CAT(mpl_assert_rel_value,counter)>( \ 334 (boost::mpl::failed ************ ( boost::mpl::assert_relation< \ 335 boost::mpl::assert_::relations( sizeof( \ 336 boost::mpl::assert_::arg rel boost::mpl::assert_::arg \ 337 ) ) \ 338 , x \ 339 , y \ 340 >::************)) 0 ) \ 341 ) \ 342 ) \ 343 /**/ 344 # else 345 # define BOOST_MPL_ASSERT_RELATION_IMPL(counter, x, rel, y) \ 346 BOOST_MPL_AUX_ASSERT_CONSTANT( \ 347 std::size_t \ 348 , BOOST_PP_CAT(mpl_assert_rel,counter) = sizeof( \ 349 boost::mpl::assert_::arg rel boost::mpl::assert_::arg \ 350 ) \ 351 ); \ 352 BOOST_MPL_AUX_ASSERT_CONSTANT( bool, BOOST_PP_CAT(mpl_assert_rel_value,counter) = (x rel y) ); \ 353 BOOST_MPL_AUX_ASSERT_CONSTANT( \ 354 std::size_t \ 355 , BOOST_PP_CAT(mpl_assertion_in_line_,counter) = sizeof( \ 356 boost::mpl::assertion_failed<BOOST_PP_CAT(mpl_assert_rel_value,counter)>( \ 357 boost::mpl::assert_rel_arg( boost::mpl::assert_relation< \ 358 boost::mpl::assert_::relations(BOOST_PP_CAT(mpl_assert_rel,counter)) \ 359 , x \ 360 , y \ 361 >() ) \ 362 ) \ 363 ) \ 364 ) \ 365 /**/ 366 # endif 367 368 # define BOOST_MPL_ASSERT_RELATION(x, rel, y) \ 369 BOOST_MPL_ASSERT_RELATION_IMPL(BOOST_MPL_AUX_PP_COUNTER(), x, rel, y) \ 370 /**/ 371 372 #else // !BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES 373 374 # if defined(BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER) 375 # define BOOST_MPL_ASSERT_RELATION(x, rel, y) \ 376 BOOST_MPL_AUX_ASSERT_CONSTANT( \ 377 std::size_t \ 378 , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \ 379 boost::mpl::assertion_failed<(x rel y)>( boost::mpl::assert_rel_arg( \ 380 boost::mpl::BOOST_MPL_AUX_ASSERT_RELATION(x,y,(&boost::mpl::operator rel))() \ 381 ) ) \ 382 ) \ 383 ) \ 384 /**/ 385 # else 386 # define BOOST_MPL_ASSERT_RELATION(x, rel, y) \ 387 BOOST_MPL_AUX_ASSERT_CONSTANT( \ 388 std::size_t \ 389 , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \ 390 boost::mpl::assertion_failed<(x rel y)>( (boost::mpl::failed ************ ( \ 391 boost::mpl::BOOST_MPL_AUX_ASSERT_RELATION(x,y,(&boost::mpl::operator rel))::************))0 ) \ 392 ) \ 393 ) \ 394 /**/ 395 # endif 396 397 #endif 398 399 400 // BOOST_MPL_ASSERT_MSG( (pred<x,...>::value), USER_PROVIDED_MESSAGE, (types<x,...>) ) 401 402 #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3202)) 403 # define BOOST_MPL_ASSERT_MSG_IMPL( counter, c, msg, types_ ) \ 404 struct msg; \ 405 typedef struct BOOST_PP_CAT(msg,counter) : boost::mpl::assert_ \ 406 { \ 407 using boost::mpl::assert_::types; \ 408 static boost::mpl::failed ************ (msg::************ assert_arg()) types_ \ 409 { return 0; } \ 410 } BOOST_PP_CAT(mpl_assert_arg,counter); \ 411 BOOST_MPL_AUX_ASSERT_CONSTANT( \ 412 std::size_t \ 413 , BOOST_PP_CAT(mpl_assertion_in_line_,counter) = sizeof( \ 414 boost::mpl::assertion<(c)>::failed( BOOST_PP_CAT(mpl_assert_arg,counter)::assert_arg() ) \ 415 ) \ 416 ) \ 417 /**/ 418 #else 419 # define BOOST_MPL_ASSERT_MSG_IMPL( counter, c, msg, types_ ) \ 420 struct msg; \ 421 typedef struct BOOST_PP_CAT(msg,counter) : boost::mpl::assert_ \ 422 { \ 423 static boost::mpl::failed ************ (msg::************ assert_arg()) types_ \ 424 { return 0; } \ 425 } BOOST_PP_CAT(mpl_assert_arg,counter); \ 426 BOOST_MPL_AUX_ASSERT_CONSTANT( \ 427 std::size_t \ 428 , BOOST_PP_CAT(mpl_assertion_in_line_,counter) = sizeof( \ 429 boost::mpl::assertion_failed<(c)>( BOOST_PP_CAT(mpl_assert_arg,counter)::assert_arg() ) \ 430 ) \ 431 ) \ 432 /**/ 433 #endif 434 435 #define BOOST_MPL_ASSERT_MSG( c, msg, types_ ) \ 436 BOOST_MPL_ASSERT_MSG_IMPL( BOOST_MPL_AUX_PP_COUNTER(), c, msg, types_ ) \ 437 /**/ 438 439 #endif // BOOST_MPL_ASSERT_HPP_INCLUDED 440