summaryrefslogtreecommitdiff
path: root/boost/contract/core/specify.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/contract/core/specify.hpp')
-rw-r--r--boost/contract/core/specify.hpp650
1 files changed, 650 insertions, 0 deletions
diff --git a/boost/contract/core/specify.hpp b/boost/contract/core/specify.hpp
new file mode 100644
index 0000000000..ef0bea9b09
--- /dev/null
+++ b/boost/contract/core/specify.hpp
@@ -0,0 +1,650 @@
+
+#ifndef BOOST_CONTRACT_SPECIFY_HPP_
+#define BOOST_CONTRACT_SPECIFY_HPP_
+
+// Copyright (C) 2008-2018 Lorenzo Caminiti
+// Distributed under the Boost Software License, Version 1.0 (see accompanying
+// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
+// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
+
+/** @file
+Specify preconditions, old value copies at body, postconditions, and exception
+guarantees
+
+Preconditions, old value copies at body, postconditions, and exception
+guarantees are all optionals but, when they are specified, they need to be
+specified in that order.
+*/
+
+#include <boost/contract/core/config.hpp>
+#include <boost/contract/detail/decl.hpp>
+#if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
+ defined(BOOST_CONTRACT_STATIC_LINK)
+ #include <boost/contract/detail/condition/cond_base.hpp>
+ #include <boost/contract/detail/condition/cond_post.hpp>
+ #include <boost/contract/detail/auto_ptr.hpp>
+ #include <boost/contract/detail/none.hpp>
+#endif
+#if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \
+ !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \
+ !defined(BOOST_CONTRACT_NO_EXCEPTS)
+ #include <boost/contract/detail/debug.hpp>
+#endif
+#include <boost/config.hpp>
+
+// NOTE: No inheritance for faster run-times (macros to avoid duplicated code).
+
+/* PRIVATE */
+
+/* @cond */
+
+// NOTE: Private copy ops below will force compile-time error is `auto c = ...`
+// is used instead of `check c = ...` but only up to C++17. C++17 strong copy
+// elision on function return values prevents this lib from generating a
+// compile-time error in those cases, but the lib will still generate a run-time
+// error according with ON_MISSING_CHECK_DECL.
+#if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
+ defined(BOOST_CONTRACT_STATIC_LINK)
+ #define BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(class_type, cond_type) \
+ private: \
+ boost::contract::detail::auto_ptr<cond_type > cond_; \
+ explicit class_type(cond_type* cond) : cond_(cond) {} \
+ class_type(class_type const& other) : cond_(other.cond_) {} \
+ class_type& operator=(class_type const& other) { \
+ cond_ = other.cond_; \
+ return *this; \
+ }
+
+ #define BOOST_CONTRACT_SPECIFY_COND_RELEASE_ cond_.release()
+#else
+ #define BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(class_type, cond_type) \
+ private: \
+ class_type() {} \
+ class_type(class_type const&) {} \
+ class_type& operator=(class_type const&) { return *this; }
+
+ #define BOOST_CONTRACT_SPECIFY_COND_RELEASE_ /* nothing */
+#endif
+
+#ifndef BOOST_CONTRACT_NO_PRECONDITIONS
+ #define BOOST_CONTRACT_SPECIFY_PRECONDITION_IMPL_ \
+ BOOST_CONTRACT_DETAIL_DEBUG(cond_); \
+ cond_->set_pre(f); \
+ return specify_old_postcondition_except<VirtualResult>( \
+ BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
+#else
+ #define BOOST_CONTRACT_SPECIFY_PRECONDITION_IMPL_ \
+ return specify_old_postcondition_except<VirtualResult>( \
+ BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
+#endif
+
+#ifndef BOOST_CONTRACT_NO_OLDS
+ #define BOOST_CONTRACT_SPECIFY_OLD_IMPL_ \
+ BOOST_CONTRACT_DETAIL_DEBUG(cond_); \
+ cond_->set_old(f); \
+ return specify_postcondition_except<VirtualResult>( \
+ BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
+#else
+ #define BOOST_CONTRACT_SPECIFY_OLD_IMPL_ \
+ return specify_postcondition_except<VirtualResult>( \
+ BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
+#endif
+
+#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
+ #define BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_ \
+ BOOST_CONTRACT_DETAIL_DEBUG(cond_); \
+ cond_->set_post(f); \
+ return specify_except(BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
+#else
+ #define BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_ \
+ return specify_except(BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
+#endif
+
+#ifndef BOOST_CONTRACT_NO_EXCEPTS
+ #define BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_ \
+ BOOST_CONTRACT_DETAIL_DEBUG(cond_); \
+ cond_->set_except(f); \
+ return specify_nothing(BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
+#else
+ #define BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_ \
+ return specify_nothing(BOOST_CONTRACT_SPECIFY_COND_RELEASE_);
+#endif
+
+/* @endcond */
+
+/* CODE */
+
+namespace boost {
+ namespace contract {
+ class virtual_;
+
+ template<typename VR>
+ class specify_precondition_old_postcondition_except;
+
+ template<typename VR>
+ class specify_old_postcondition_except;
+
+ template<typename VR>
+ class specify_postcondition_except;
+
+ class specify_except;
+ }
+}
+
+namespace boost { namespace contract {
+
+/**
+Used to prevent setting other contract conditions after exception guarantees.
+
+This class has no member function so it is used to prevent specifying additional
+functors to check any other contract.
+This object is internally constructed by this library when users specify
+contracts calling @RefFunc{boost::contract::function} and similar functions
+(that is why this class does not have a public constructor).
+
+@see @RefSect{tutorial, Tutorial}
+*/
+class specify_nothing { // Privately copyable (as *).
+public:
+ /**
+ Destruct this object.
+
+ @b Throws: This can throw in case programmers specify failure handlers that
+ throw exceptions instead of terminating the program (see
+ @RefSect{advanced.throw_on_failures__and__noexcept__,
+ Throw on Failure}).
+ (This is declared @c noexcept(false) since C++11.)
+ */
+ ~specify_nothing() BOOST_NOEXCEPT_IF(false) {}
+
+ // No set member function here.
+
+/** @cond */
+private:
+ BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(specify_nothing,
+ boost::contract::detail::cond_base)
+
+ // Friends (used to limit library's public API).
+
+ friend class check;
+
+ template<typename VR>
+ friend class specify_precondition_old_postcondition_except;
+
+ template<typename VR>
+ friend class specify_old_postcondition_except;
+
+ template<typename VR>
+ friend class specify_postcondition_except;
+
+ friend class specify_except;
+/** @endcond */
+};
+
+/**
+Allow to specify exception guarantees.
+
+Allow to specify the functor this library will call to check exception
+guarantees.
+This object is internally constructed by this library when users specify
+contracts calling @RefFunc{boost::contract::function} and similar functions
+(that is why this class does not have a public constructor).
+
+@see @RefSect{tutorial.exception_guarantees, Exception Guarantees}
+*/
+class specify_except { // Privately copyable (as *).
+public:
+ /**
+ Destruct this object.
+
+ @b Throws: This can throw in case programmers specify failure handlers that
+ throw exceptions instead of terminating the program (see
+ @RefSect{advanced.throw_on_failures__and__noexcept__,
+ Throw on Failure}).
+ (This is declared @c noexcept(false) since C++11.)
+ */
+ ~specify_except() BOOST_NOEXCEPT_IF(false) {}
+
+ /**
+ Allow to specify exception guarantees.
+
+ @param f Nullary functor called by this library to check exception
+ guarantees @c f().
+ Assertions within this functor are usually programmed using
+ @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
+ call to this functor indicates a contract assertion failure (and
+ will result in this library calling
+ @RefFunc{boost::contract::except_failure}).
+ This functor should capture variables by (constant) references
+ (to access the values they will have at function exit).
+
+ @return After exception guarantees have been specified, the object returned
+ by this function does not allow to specify any additional contract.
+ */
+ template<typename F>
+ specify_nothing except(F const& f) {
+ BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_
+ }
+
+/** @cond */
+private:
+ BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(specify_except,
+ boost::contract::detail::cond_base)
+
+ // Friends (used to limit library's public API).
+
+ friend class check;
+
+ template<typename VR>
+ friend class specify_precondition_old_postcondition_except;
+
+ template<typename VR>
+ friend class specify_old_postcondition_except;
+
+ template<typename VR>
+ friend class specify_postcondition_except;
+/** @endcond */
+};
+
+/**
+Allow to specify postconditions or exception guarantees.
+
+Allow to specify functors this library will call to check postconditions or
+exception guarantees.
+This object is internally constructed by this library when users specify
+contracts calling @RefFunc{boost::contract::function} and similar functions
+(that is why this class does not have a public constructor).
+
+@see @RefSect{tutorial.postconditions, Postconditions},
+ @RefSect{tutorial.exception_guarantees, Exception Guarantees}
+
+@tparam VirtualResult Return type of the enclosing function declaring the
+ contract if that function is either a virtual public
+ function or a public function override.
+ Otherwise, this type is always @c void.
+*/
+template<typename VirtualResult = void>
+class specify_postcondition_except { // Privately copyable (as *).
+public:
+ /**
+ Destruct this object.
+
+ @b Throws: This can throw in case programmers specify failure handlers that
+ throw exceptions instead of terminating the program (see
+ @RefSect{advanced.throw_on_failures__and__noexcept__,
+ Throw on Failure}).
+ (This is declared @c noexcept(false) since C++11.)
+ */
+ ~specify_postcondition_except() BOOST_NOEXCEPT_IF(false) {}
+
+ /**
+ Allow to specify postconditions.
+
+ @param f Functor called by this library to check postconditions
+ @c f(...).
+ Assertions within this functor are usually programmed using
+ @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
+ call to this functor indicates a contract assertion failure (and
+ will result in this library calling
+ @RefFunc{boost::contract::postcondition_failure}).
+ This functor should capture variables by (constant) references
+ (to access the values they will have at function exit).
+ This functor must be a nullary functor if @c VirtualResult is
+ @c void, otherwise it must be a unary functor accepting the
+ return value as a parameter of type <c>VirtualResult const&</c>
+ (to avoid extra copies of the return value, or of type
+ @c VirtualResult or <c>VirtualResult const</c> if extra copies
+ of the return value are irrelevant).
+
+ @return After postconditions have been specified, the object returned by
+ this function allows to optionally specify exception guarantees.
+ */
+ template<typename F>
+ specify_except postcondition(F const& f) {
+ BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_
+ }
+
+ /**
+ Allow to specify exception guarantees.
+
+ @param f Nullary functor called by this library to check exception
+ guarantees @c f().
+ Assertions within this functor are usually programmed using
+ @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
+ call to this functor indicates a contract assertion failure (and
+ will result in this library calling
+ @RefFunc{boost::contract::except_failure}).
+ This functor should capture variables by (constant) references
+ (to access the values they will have at function exit).
+
+ @return After exception guarantees have been specified, the object returned
+ by this function does not allow to specify any additional contract.
+ */
+ template<typename F>
+ specify_nothing except(F const& f) {
+ BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_
+ }
+
+/** @cond */
+private:
+ BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(
+ specify_postcondition_except,
+ boost::contract::detail::cond_post<typename
+ boost::contract::detail::none_if_void<VirtualResult>::type>
+ )
+
+ // Friends (used to limit library's public API).
+
+ friend class check;
+ friend class specify_precondition_old_postcondition_except<VirtualResult>;
+ friend class specify_old_postcondition_except<VirtualResult>;
+/** @endcond */
+};
+
+/**
+Allow to specify old value copies at body, postconditions, and exception
+guarantees.
+
+Allow to specify functors this library will call to copy old value at body,
+check postconditions, and check exception guarantees.
+This object is internally constructed by this library when users specify
+contracts calling @RefFunc{boost::contract::function} and similar functions
+(that is why this class does not have a public constructor).
+
+@see @RefSect{advanced.old_value_copies_at_body, Old Value Copies at Body},
+ @RefSect{tutorial.postconditions, Postconditions},
+ @RefSect{tutorial.exception_guarantees, Exception Guarantees}
+
+@tparam VirtualResult Return type of the enclosing function declaring the
+ contract if that function is either a virtual public
+ function or a public function override.
+ Otherwise, this type is always @c void.
+*/
+template<typename VirtualResult = void>
+class specify_old_postcondition_except { // Privately copyable (as *).
+public:
+ /**
+ Destruct this object.
+
+ @b Throws: This can throw in case programmers specify failure handlers that
+ throw exceptions instead of terminating the program (see
+ @RefSect{advanced.throw_on_failures__and__noexcept__,
+ Throw on Failure}).
+ (This is declared @c noexcept(false) since C++11.)
+ */
+ ~specify_old_postcondition_except() BOOST_NOEXCEPT_IF(false) {}
+
+ /**
+ Allow to specify old value copies at body.
+
+ It should often be sufficient to initialize old value pointers as soon as
+ they are declared, without using this function (see
+ @RefSect{advanced.old_value_copies_at_body, Old Value Copies at Body}).
+
+ @param f Nullary functor called by this library @c f() to assign old
+ value copies just before the body is executed but after entry
+ invariants (when they apply) and preconditions are checked.
+ Old value pointers within this functor call are usually assigned
+ using @RefMacro{BOOST_CONTRACT_OLDOF}.
+ Any exception thrown by a call to this functor will result in
+ this library calling @RefFunc{boost::contract::old_failure}
+ (because old values could not be copied to check postconditions
+ and exception guarantees).
+ This functor should capture old value pointers by references so
+ they can be assigned (all other variables needed to evaluate old
+ value expressions can be captured by (constant) value, or better
+ by (constant) reference to avoid extra copies).
+
+ @return After old value copies at body have been specified, the object
+ returned by this function allows to optionally specify
+ postconditions and exception guarantees.
+ */
+ template<typename F>
+ specify_postcondition_except<VirtualResult> old(F const& f) {
+ BOOST_CONTRACT_SPECIFY_OLD_IMPL_
+ }
+
+ /**
+ Allow to specify postconditions.
+
+ @param f Functor called by this library to check postconditions
+ @c f(...).
+ Assertions within this functor are usually programmed using
+ @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
+ call to this functor indicates a contract assertion failure (and
+ will result in this library calling
+ @RefFunc{boost::contract::postcondition_failure}).
+ This functor should capture variables by (constant) references
+ (to access the values they will have at function exit).
+ This functor must be a nullary functor if @c VirtualResult is
+ @c void, otherwise it must be a unary functor accepting the
+ return value as a parameter of type <c>VirtualResult const&</c>
+ (to avoid extra copies of the return value, or of type
+ @c VirtualResult or <c>VirtualResult const</c> if extra copies
+ of the return value are irrelevant).
+
+ @return After postconditions have been specified, the object returned by
+ this function allows to optionally specify exception guarantees.
+ */
+ template<typename F>
+ specify_except postcondition(F const& f) {
+ BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_
+ }
+
+ /**
+ Allow to specify exception guarantees.
+
+ @param f Nullary functor called by this library to check exception
+ guarantees @c f().
+ Assertions within this functor are usually programmed using
+ @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
+ call to this functor indicates a contract assertion failure (and
+ will result in this library calling
+ @RefFunc{boost::contract::except_failure}).
+ This functor should capture variables by (constant) references
+ (to access the values they will have at function exit).
+
+ @return After exception guarantees have been specified, the object returned
+ by this function does not allow to specify any additional contract.
+ */
+ template<typename F>
+ specify_nothing except(F const& f) {
+ BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_
+ }
+
+/** @cond */
+private:
+ BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(
+ specify_old_postcondition_except,
+ boost::contract::detail::cond_post<typename
+ boost::contract::detail::none_if_void<VirtualResult>::type>
+ )
+
+ // Friends (used to limit library's public API).
+
+ friend class check;
+ friend class specify_precondition_old_postcondition_except<VirtualResult>;
+
+ template<class C>
+ friend specify_old_postcondition_except<> constructor(C*);
+
+ template<class C>
+ friend specify_old_postcondition_except<> destructor(C*);
+/** @endcond */
+};
+
+/**
+Allow to specify preconditions, old value copies at body, postconditions, and
+exception guarantees.
+
+Allow to specify functors this library will call to check preconditions, copy
+old values at body, check postconditions, and check exception guarantees.
+This object is internally constructed by this library when users specify
+contracts calling @RefFunc{boost::contract::function} and similar functions
+(that is why this class does not have a public constructor).
+
+@see @RefSect{tutorial.preconditions, Preconditions},
+ @RefSect{advanced.old_value_copies_at_body, Old Value Copies at Body},
+ @RefSect{tutorial.postconditions, Postconditions},
+ @RefSect{tutorial.exception_guarantees, Exception Guarantees}
+
+@tparam VirtualResult Return type of the enclosing function declaring the
+ contract if that function is either a virtual public
+ function or a public function override.
+ Otherwise, this type is always @c void.
+*/
+template<
+ typename VirtualResult /* = void (already in fwd decl from decl.hpp) */
+ #ifdef BOOST_CONTRACT_DETAIL_DOXYGEN
+ = void
+ #endif
+>
+class specify_precondition_old_postcondition_except { // Priv. copyable (as *).
+public:
+ /**
+ Destruct this object.
+
+ @b Throws: This can throw in case programmers specify failure handlers that
+ throw exceptions instead of terminating the program (see
+ @RefSect{advanced.throw_on_failures__and__noexcept__,
+ Throw on Failure}).
+ (This is declared @c noexcept(false) since C++11.)
+ */
+ ~specify_precondition_old_postcondition_except() BOOST_NOEXCEPT_IF(false) {}
+
+ /**
+ Allow to specify preconditions.
+
+ @param f Nullary functor called by this library to check preconditions
+ @c f().
+ Assertions within this functor are usually programmed using
+ @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
+ call to this functor indicates a contract assertion failure (and
+ will result in this library calling
+ @RefFunc{boost::contract::precondition_failure}).
+ This functor should capture variables by (constant) value, or
+ better by (constant) reference (to avoid extra copies).
+
+ @return After preconditions have been specified, the object returned by this
+ function allows to optionally specify old value copies at body,
+ postconditions, and exception guarantees.
+ */
+ template<typename F>
+ specify_old_postcondition_except<VirtualResult> precondition(F const& f) {
+ BOOST_CONTRACT_SPECIFY_PRECONDITION_IMPL_
+ }
+
+ /**
+ Allow to specify old value copies at body.
+
+ It should often be sufficient to initialize old value pointers as soon as
+ they are declared, without using this function (see
+ @RefSect{advanced.old_value_copies_at_body, Old Value Copies at Body}).
+
+ @param f Nullary functor called by this library @c f() to assign old
+ value copies just before the body is executed but after entry
+ invariants (when they apply) and preconditions are checked.
+ Old value pointers within this functor call are usually assigned
+ using @RefMacro{BOOST_CONTRACT_OLDOF}.
+ Any exception thrown by a call to this functor will result in
+ this library calling @RefFunc{boost::contract::old_failure}
+ (because old values could not be copied to check postconditions
+ and exception guarantees).
+ This functor should capture old value pointers by references so
+ they can be assigned (all other variables needed to evaluate old
+ value expressions can be captured by (constant) value, or better
+ by (constant) reference to avoid extra copies).
+
+ @return After old value copies at body have been specified, the object
+ returned by this functions allows to optionally specify
+ postconditions and exception guarantees.
+ */
+ template<typename F>
+ specify_postcondition_except<VirtualResult> old(F const& f) {
+ BOOST_CONTRACT_SPECIFY_OLD_IMPL_
+ }
+
+ /**
+ Allow to specify postconditions.
+
+ @param f Functor called by this library to check postconditions
+ @c f(...).
+ Assertions within this functor are usually programmed using
+ @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
+ call to this functor indicates a contract assertion failure (and
+ will result in this library calling
+ @RefFunc{boost::contract::postcondition_failure}).
+ This functor should capture variables by (constant) references
+ (to access the values they will have at function exit).
+ This functor must be a nullary functor if @c VirtualResult is
+ @c void, otherwise it must be a unary functor accepting the
+ return value as a parameter of type <c>VirtualResult const&</c>
+ (to avoid extra copies of the return value, or of type
+ @c VirtualResult or <c>VirtualResult const</c> if extra copies
+ of the return value are irrelevant).
+
+ @return After postconditions have been specified, the object returned by
+ this function allows to optionally specify exception guarantees.
+ */
+ template<typename F>
+ specify_except postcondition(F const& f) {
+ BOOST_CONTRACT_SPECIFY_POSTCONDITION_IMPL_
+ }
+
+ /**
+ Allow to specify exception guarantees.
+
+ @param f Nullary functor called by this library to check exception
+ guarantees @c f().
+ Assertions within this functor are usually programmed using
+ @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a
+ call to this functor indicates a contract assertion failure (and
+ will result in this library calling
+ @RefFunc{boost::contract::except_failure}).
+ This functor should capture variables by (constant) references
+ (to access the values they will have at function exit).
+
+ @return After exception guarantees have been specified, the object returned
+ by this function does not allow to specify any additional contract.
+ */
+ template<typename F>
+ specify_nothing except(F const& f) {
+ BOOST_CONTRACT_SPECIFY_EXCEPT_IMPL_
+ }
+
+/** @cond */
+private:
+ BOOST_CONTRACT_SPECIFY_CLASS_IMPL_(
+ specify_precondition_old_postcondition_except,
+ boost::contract::detail::cond_post<typename
+ boost::contract::detail::none_if_void<VirtualResult>::type>
+ )
+
+ // Friends (used to limit library's public API).
+
+ friend class check;
+ friend specify_precondition_old_postcondition_except<> function();
+
+ template<class C>
+ friend specify_precondition_old_postcondition_except<> public_function();
+
+ template<class C>
+ friend specify_precondition_old_postcondition_except<> public_function(C*);
+
+ template<class C>
+ friend specify_precondition_old_postcondition_except<> public_function(
+ virtual_*, C*);
+
+ template<typename VR, class C>
+ friend specify_precondition_old_postcondition_except<VR> public_function(
+ virtual_*, VR&, C*);
+
+ BOOST_CONTRACT_DETAIL_DECL_FRIEND_OVERRIDING_PUBLIC_FUNCTIONS_Z(1,
+ O, VR, F, C, Args, v, r, f, obj, args)
+/** @endcond */
+};
+
+} } // namespace
+
+#endif // #include guard
+