|
|
@@ -26,8 +26,23 @@
|
|
|
#define NUM(...) SELECT_5TH(__VA_ARGS__, FOURPLUS, THREE, TWO, ONE, throwaway)
|
|
|
#define SELECT_5TH(a1, a2, a3, a4, a5, ...) a5
|
|
|
|
|
|
-
|
|
|
namespace contract {
|
|
|
+ template <typename expect>
|
|
|
+ class ensure_t {
|
|
|
+ private:
|
|
|
+ std::function<bool()> passes_;
|
|
|
+ std::string message_;
|
|
|
+ public:
|
|
|
+ template <typename F>
|
|
|
+ ensure_t(F && passes, std::string const & msg, char const * = "")
|
|
|
+ : passes_(passes), message_(msg) {}
|
|
|
+ ~ensure_t() noexcept(false) {
|
|
|
+ if (!std::uncaught_exception() && !passes_()) {
|
|
|
+ throw expect{message_};
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
template <typename except>
|
|
|
void _contract_impl(bool expr, std::string const & msg, char const * = "") {
|
|
|
if ( ! expr ) throw except{ msg };
|
|
|
@@ -101,8 +116,9 @@ namespace contract {
|
|
|
* ensures( bool-expr, error_type, custom_msg )
|
|
|
*/
|
|
|
#define ensures( ... ) \
|
|
|
- contract::_contract_impl<EXCEPT_T(__VA_ARGS__, std::runtime_error)>( \
|
|
|
- FIRST(__VA_ARGS__), \
|
|
|
+ contract::ensure_t<EXCEPT_T(__VA_ARGS__, std::runtime_error)>\
|
|
|
+ CONCAT(contract_ensures_, __LINE__)( \
|
|
|
+ [&]() { return FIRST(__VA_ARGS__); }, \
|
|
|
EXCEPT_MSG(__VA_ARGS__ , \
|
|
|
DEF_MSG("postcondition", FIRST(__VA_ARGS__))) \
|
|
|
)
|