|
|
@@ -115,7 +115,6 @@ namespace contract {
|
|
|
DEF_MSG("postcondition", FIRST(__VA_ARGS__))) \
|
|
|
)
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
* RVO works if expr is an rvalue, but not if it is an
|
|
|
* lvalue. e.g:
|
|
|
@@ -155,3 +154,41 @@ namespace contract {
|
|
|
return _; \
|
|
|
}( )
|
|
|
#endif
|
|
|
+
|
|
|
+namespace contract {
|
|
|
+ template <typename T>
|
|
|
+ struct postcondition_helper {
|
|
|
+ void(*deleter)(T const*);
|
|
|
+ T const* object;
|
|
|
+
|
|
|
+ postcondition_helper() = default;
|
|
|
+ postcondition_helper(postcondition_helper &&) = delete;
|
|
|
+ postcondition_helper(postcondition_helper const&) = delete;
|
|
|
+ ~postcondition_helper() { if (deleter) deleter(object); }
|
|
|
+
|
|
|
+ T const & operator=(T const & rhs) {
|
|
|
+ object = &rhs;
|
|
|
+ deleter = [](void const*) {};
|
|
|
+ return rhs;
|
|
|
+ }
|
|
|
+
|
|
|
+ T const & operator=(T && rhs) {
|
|
|
+ object = new T(rhs);
|
|
|
+ deleter = [](T const* ptr) { delete ptr; };
|
|
|
+ return *object;
|
|
|
+ }
|
|
|
+
|
|
|
+ T const * operator->() const { return object; }
|
|
|
+
|
|
|
+ bool operator==(T const & rhs) const { return *object == rhs; }
|
|
|
+ bool operator!=(T const & rhs) const { return *object != rhs; }
|
|
|
+ bool operator<=(T const & rhs) const { return *object <= rhs; }
|
|
|
+ bool operator< (T const & rhs) const { return *object < rhs; }
|
|
|
+ bool operator>=(T const & rhs) const { return *object >= rhs; }
|
|
|
+ bool operator> (T const & rhs) const { return *object > rhs; }
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+#define contract_postconditions(type) \
|
|
|
+ contract::postcondition_helper<type> $return
|
|
|
+#define contract_return( ... ) return ($return = __VA_ARGS__)
|