|
|
@@ -19,8 +19,13 @@
|
|
|
#undef STRING
|
|
|
#define STRING(A) STRING2(A)
|
|
|
|
|
|
-#undef GET_MACRO_3
|
|
|
-#define GET_MACRO_3(_1,_2,_3,NAME,...) NAME
|
|
|
+/* expands to the first argument */
|
|
|
+#define FIRST(...) FIRST_HELPER(__VA_ARGS__, throwaway)
|
|
|
+#define FIRST_HELPER(first, ...) first
|
|
|
+
|
|
|
+#define NUM(...) SELECT_5TH(__VA_ARGS__, FOURPLUS, THREE, TWO, ONE, throwaway)
|
|
|
+#define SELECT_5TH(a1, a2, a3, a4, a5, ...) a5
|
|
|
+
|
|
|
|
|
|
namespace contract {
|
|
|
template <typename except>
|
|
|
@@ -34,17 +39,21 @@ namespace contract {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-#define FIRST_ELEMENT( X, ... ) X
|
|
|
-#define SECOND_ELEMENT( X, Y, ... ) Y
|
|
|
+#define EXCEPT_T_TWO(X, Y) Y
|
|
|
+#define EXCEPT_T_THREE(X, Y, Z) Z
|
|
|
+#define EXCEPT_T_FOURPLUS(X, Y, Z, ...) Z
|
|
|
|
|
|
-#define exception_type( ... ) GET_MACRO_3( __VA_ARGS__, SECOND_ELEMENT, FIRST_ELEMENT, FIRST_ELEMENT )( __VA_ARGS__ )
|
|
|
+#define EXCEPT_T(...) EXCEPT_T_HELPER(NUM(__VA_ARGS__), __VA_ARGS__)
|
|
|
+#define EXCEPT_T_HELPER(N, ...) EXCEPT_T_HELPER2(N, __VA_ARGS__)
|
|
|
+#define EXCEPT_T_HELPER2(N, ...) EXCEPT_T_##N(__VA_ARGS__)
|
|
|
|
|
|
-#define IGNORE( ... )
|
|
|
+#define EXCEPT_MSG_TWO(X, Y) Y
|
|
|
+#define EXCEPT_MSG_THREE(X, Y, Z) Y
|
|
|
+#define EXCEPT_MSG_FOURPLUS(X, Y, Z, ...) Y
|
|
|
|
|
|
-#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__ )
|
|
|
+#define EXCEPT_MSG(...) EXCEPT_MSG_HELPER(NUM(__VA_ARGS__), __VA_ARGS__)
|
|
|
+#define EXCEPT_MSG_HELPER(N, ...) EXCEPT_MSG_HELPER2(N, __VA_ARGS__)
|
|
|
+#define EXCEPT_MSG_HELPER2(N, ...) EXCEPT_MSG_##N(__VA_ARGS__)
|
|
|
|
|
|
#if defined( __clang__ ) || defined( __GNUC__ )
|
|
|
# define FUNCTION STRING(__PRETTY_FUNCTION__)
|
|
|
@@ -54,11 +63,11 @@ namespace contract {
|
|
|
# define FUNCTION "???"
|
|
|
#endif
|
|
|
|
|
|
-#define get_default_message( header, expr ) \
|
|
|
- header #expr ". in " FUNCTION "(" __FILE__ ":" STRING( __LINE__ ) ")"
|
|
|
+#define DEF_MSG( header, expr ) \
|
|
|
+ header " failed: " STRING(expr) ". in " FUNCTION "(" __FILE__ ":" STRING( __LINE__ ) ")"
|
|
|
|
|
|
-#define get_subs_message( header, bool_expr, rval_expr ) \
|
|
|
- header #bool_expr " [ with _ = " #rval_expr " ]. in " FUNCTION "(" __FILE__ ":" STRING( __LINE__ ) ")"
|
|
|
+#define SUB_MSG( header, bool_expr, rval_expr ) \
|
|
|
+ header " failed: " STRING(bool_expr) " [ with _ = " STRING(rval_expr) " ]. in " FUNCTION "(" __FILE__ ":" STRING( __LINE__ ) ")"
|
|
|
|
|
|
/*
|
|
|
* Usage:
|
|
|
@@ -66,10 +75,12 @@ namespace contract {
|
|
|
* expects( bool-expr, custom_msg )
|
|
|
* expects( bool-expr, error_type, custom_msg )
|
|
|
*/
|
|
|
-#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 expects( ... ) \
|
|
|
+ contract::_contract_impl<EXCEPT_T( __VA_ARGS__, std::logic_error)>( \
|
|
|
+ FIRST(__VA_ARGS__), \
|
|
|
+ EXCEPT_MSG(__VA_ARGS__, \
|
|
|
+ DEF_MSG("precondition", FIRST(__VA_ARGS__))) \
|
|
|
+ )
|
|
|
|
|
|
/*
|
|
|
* Usage:
|
|
|
@@ -87,10 +98,12 @@ namespace contract {
|
|
|
* ensures( bool-expr, custom_msg )
|
|
|
* ensures( bool-expr, error_type, custom_msg )
|
|
|
*/
|
|
|
-#define ensures( cond, ... ) \
|
|
|
- contract::_contract_impl< exception_type( std::runtime_error, ##__VA_ARGS__ )>( \
|
|
|
- cond pop_exception( __VA_ARGS__ ) , \
|
|
|
- get_default_message( "postcondition failed: ", cond ) )
|
|
|
+#define ensures( ... ) \
|
|
|
+ contract::_contract_impl<EXCEPT_T(__VA_ARGS__, std::runtime_error)>( \
|
|
|
+ FIRST(__VA_ARGS__), \
|
|
|
+ EXCEPT_MSG(__VA_ARGS__ , \
|
|
|
+ DEF_MSG("postcondition", FIRST(__VA_ARGS__))) \
|
|
|
+ )
|
|
|
|
|
|
|
|
|
/**
|
|
|
@@ -113,20 +126,22 @@ namespace contract {
|
|
|
* ensure-expr - A special boolean expression using the token '_'.
|
|
|
*/
|
|
|
#if __cplusplus < 201300
|
|
|
-#define return_ensures( expr, cond, ... ) \
|
|
|
+#define return_ensures( expr, ... ) \
|
|
|
[ & ]( ) { \
|
|
|
decltype((expr)) _ = expr; \
|
|
|
- contract::_contract_impl< exception_type( std::runtime_error, ##__VA_ARGS__ ) >( \
|
|
|
- cond pop_exception( __VA_ARGS__ ) , \
|
|
|
- get_subs_message( "postcondition failed: ", cond, expr ) ); \
|
|
|
+ contract::_contract_impl<EXCEPT_T(__VA_ARGS__, std::runtime_error)>( \
|
|
|
+ FIRST(__VA_ARGS__), \
|
|
|
+ EXCEPT_MSG(__VA_ARGS__, \
|
|
|
+ SUB_MSG("postcondition", FIRST(__VA_ARGS__), expr))); \
|
|
|
return _; \
|
|
|
}( )
|
|
|
#else
|
|
|
#define return_ensures( expr, cond, ... ) \
|
|
|
[ _ = expr ]( ) { \
|
|
|
- contract::_contract_impl< exception_type( std::runtime_error, ##__VA_ARGS__ ) >( \
|
|
|
- cond pop_exception( __VA_ARGS__ ) , \
|
|
|
- get_subs_message( "postcondition failed: ", cond, expr ) ); \
|
|
|
+ contract::_contract_impl<EXCEPT_T(__VA_ARGS__, std::runtime_error)>( \
|
|
|
+ FIRST(__VA_ARGS__), \
|
|
|
+ EXCEPT_MSG(__VA_ARGS__, \
|
|
|
+ SUB_MSG("postcondition", FIRST(__VA_ARGS__), expr))); \
|
|
|
return _; \
|
|
|
}( )
|
|
|
#endif
|