| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- //
- // require.hpp
- // gameutils
- //
- // Created by Sam Jaffe on 8/19/16.
- //
- #pragma once
- #include <stdexcept>
- #undef CONCAT2
- #define CONCAT2(A, B) A##B
- #undef CONCAT
- #define CONCAT(A, B) CONCAT2(A, B)
- #undef STRING2
- #define STRING2(A) #A
- #undef STRING
- #define STRING(A) STRING2(A)
- #undef GET_MACRO_3
- #define GET_MACRO_3(_1,_2,_3,NAME,...) NAME
- namespace contract {
- template <typename except>
- void _contract_impl(bool expr, std::string const & msg, char const * = "") {
- if ( ! expr ) throw except{ msg };
- }
-
- template <typename except>
- void _contract_impl(bool expr, char const * msg, char const * = "") {
- if ( ! expr ) throw except{ msg };
- }
- }
- #define FIRST_ELEMENT( X, ... ) X
- #define SECOND_ELEMENT( X, Y, ... ) Y
- #define exception_type( ... ) GET_MACRO_3( __VA_ARGS__, SECOND_ELEMENT, FIRST_ELEMENT, FIRST_ELEMENT )( __VA_ARGS__ )
- #define IGNORE( ... )
- #define COMMA_FIRST_ELEMENT( X, ... ) , X
- #define COMMA_SECOND_ELEMENT( X, Y, ... ) , Y
- #define pop_exception( ... ) GET_MACRO_3( "", ##__VA_ARGS__, COMMA_SECOND_ELEMENT, COMMA_FIRST_ELEMENT, IGNORE )( __VA_ARGS__ )
- #if defined( __clang__ ) || defined( __GNUC__ )
- # define FUNCTION STRING(__PRETTY_FUNCTION__)
- #elif defined( _MSC_VER )
- # define FUNCTION STRING(__FUNCTION__)
- #else
- # define FUNCTION "???"
- #endif
- #define get_default_message( header, expr ) \
- header #expr ". in " FUNCTION "(" __FILE__ ":" STRING( __LINE__ ) ")"
- #define expects( expr, ... ) \
- contract::_contract_impl< exception_type( std::logic_error, ##__VA_ARGS__ ) >( \
- expr pop_exception( __VA_ARGS__ ), \
- get_default_message( "precondition failed: ", expr ) )
- /*
- #define ensures( cond, ... ) \
- contract::_contract_impl< exception_type( std::runtime_error, ##__VA_ARGS__ )>( \
- cond , ##__VA_ARGS__ , \
- get_default_message( "postcondition failed: ", cond ) )
- */
- /**
- * RVO works if expr is an rvalue, but not if it is an
- * lvalue. e.g:
- * return ensures( expression, condition );
- * will rvo the object (if expression is rvo-able)
- * but
- * return ensures( var, condition );
- * will not, instead copies
- * By making _ an argument, both options will move
- */
- #define ensures( expr, cond, ... ) \
- [ & ]( ) { \
- decltype((expr)) _ = expr; \
- contract::_contract_impl< exception_type( std::runtime_error, ##__VA_ARGS__ ) >( \
- cond , ##__VA_ARGS__ , \
- get_default_message( "postcondition failed: ", cond ) ); \
- return _; \
- }( )
|