summaryrefslogtreecommitdiff
path: root/boost/contract/core/access.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/contract/core/access.hpp')
-rw-r--r--boost/contract/core/access.hpp183
1 files changed, 183 insertions, 0 deletions
diff --git a/boost/contract/core/access.hpp b/boost/contract/core/access.hpp
new file mode 100644
index 0000000000..ba8334ba0d
--- /dev/null
+++ b/boost/contract/core/access.hpp
@@ -0,0 +1,183 @@
+
+#ifndef BOOST_CONTRACT_ACCESS_HPP_
+#define BOOST_CONTRACT_ACCESS_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
+Allow to declare invariants, base types, etc all as private members.
+*/
+
+// IMPORTANT: Included by contract_macro.hpp so must #if-guard all its includes.
+#include <boost/contract/core/config.hpp>
+#if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
+ defined(BOOST_CONTRACT_STATIC_LINK)
+ #include <boost/contract/detail/decl.hpp>
+ #include <boost/contract/detail/type_traits/mirror.hpp>
+#endif
+#ifndef BOOST_CONTRACT_NO_INVARIANTS
+ #include <boost/contract/detail/debug.hpp>
+ #include <boost/function_types/property_tags.hpp>
+ #include <boost/mpl/vector.hpp>
+#endif
+
+namespace boost { namespace contract {
+
+#if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
+ defined(BOOST_CONTRACT_STATIC_LINK)
+ class virtual_;
+
+ namespace detail {
+ BOOST_CONTRACT_DETAIL_DECL_DETAIL_COND_SUBCONTRACTING_Z(1,
+ /* is_friend = */ 0, OO, RR, FF, CC, AArgs);
+ }
+#endif
+#ifndef BOOST_CONTRACT_NO_INVARIANTS
+ namespace detail {
+ template<typename RR, class CC>
+ class cond_inv;
+ }
+#endif
+
+/**
+Friend this class to declare invariants and base types as private members.
+
+Declare this class a friend of the user-defined class specifying the contracts
+in order to declare the invariant functions and the base types @c typedef as
+non-public members:
+
+@code
+class u :
+ #define BASES public b, private w
+ BASES
+{
+ friend class boost::contract::access;
+
+ typedef BOOST_CONTRACT_BASES(BASES) base_types; // Private.
+ #undef BASES
+
+ void invariant() const { ... } // Private.
+
+public:
+ ...
+};
+@endcode
+
+In real code, programmers will likely chose to declare this class as friend so
+to fully control public interfaces of their user-defined classes.
+This class is not intended to be directly used by programmers a part from
+declaring it @c friend (and that is why this class does not have any public
+member and it is not copyable).
+
+@warning Not declaring this class friend of user-defined classes will cause
+ compiler errors on some compilers (e.g., MSVC) because the private
+ members needed to check the contracts will not be accessible.
+ On other compilers (e.g., GCC and CLang), the private access will
+ instead fail SFINAE and no compiler error will be reported while
+ invariants and subcontracting will be silently skipped at run-time.
+ Therefore, programmers must make sure to either declare this class
+ as friend (preferred) or to always declare invariant functions and
+ base types @c typedef as public members.
+
+@see @RefSect{advanced.access_specifiers, Access Specifiers}
+*/
+class access { // Non-copyable (see below).
+/** @cond */
+private: // No public APIs (so users cannot use it directly by mistake).
+
+ access(); // Should never be constructed (not even internally).
+ ~access();
+
+ // No boost::noncopyable to avoid its overhead when contracts disabled.
+ access(access&);
+ access& operator=(access&);
+
+ #if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
+ defined(BOOST_CONTRACT_STATIC_LINK)
+ BOOST_CONTRACT_DETAIL_MIRROR_HAS_TYPE(has_base_types,
+ BOOST_CONTRACT_BASES_TYPEDEF)
+
+ template<class C>
+ struct base_types_of {
+ typedef typename C::BOOST_CONTRACT_BASES_TYPEDEF type;
+ };
+ #endif
+
+ #ifndef BOOST_CONTRACT_NO_INVARIANTS
+ BOOST_CONTRACT_DETAIL_MIRROR_HAS_MEMBER_FUNCTION(
+ has_static_invariant_f, BOOST_CONTRACT_STATIC_INVARIANT_FUNC)
+
+ BOOST_CONTRACT_DETAIL_MIRROR_HAS_STATIC_MEMBER_FUNCTION(
+ has_static_invariant_s, BOOST_CONTRACT_STATIC_INVARIANT_FUNC)
+
+ template<class C>
+ struct has_static_invariant : has_static_invariant_s<C, void,
+ boost::mpl::vector<> > {};
+
+ template<class C>
+ static void static_invariant() {
+ C::BOOST_CONTRACT_STATIC_INVARIANT_FUNC();
+ }
+
+ template<class C>
+ class static_invariant_addr { // Class so to pass it as tparam.
+ typedef void (*func_ptr)();
+ public:
+ static func_ptr apply() {
+ return &C::BOOST_CONTRACT_STATIC_INVARIANT_FUNC;
+ }
+ };
+
+ BOOST_CONTRACT_DETAIL_MIRROR_HAS_MEMBER_FUNCTION(
+ has_invariant_f, BOOST_CONTRACT_INVARIANT_FUNC)
+
+ BOOST_CONTRACT_DETAIL_MIRROR_HAS_STATIC_MEMBER_FUNCTION(
+ has_invariant_s, BOOST_CONTRACT_INVARIANT_FUNC)
+
+ template<class C>
+ struct has_cv_invariant : has_invariant_f<C, void, boost::mpl::vector<>,
+ boost::function_types::cv_qualified> {};
+
+ template<class C>
+ struct has_const_invariant : has_invariant_f<C, void, boost::mpl::
+ vector<>, boost::function_types::const_qualified> {};
+
+ template<class C>
+ static void cv_invariant(C const volatile* obj) {
+ BOOST_CONTRACT_DETAIL_DEBUG(obj);
+ obj->BOOST_CONTRACT_INVARIANT_FUNC();
+ }
+
+ template<class C>
+ static void const_invariant(C const* obj) {
+ BOOST_CONTRACT_DETAIL_DEBUG(obj);
+ obj->BOOST_CONTRACT_INVARIANT_FUNC();
+ }
+ #endif
+
+ // Friends (used to limit library's public API).
+ // NOTE: Using friends here and in all other places in this library
+ // does not increase compilation times (I experimented replacing all
+ // friends with public and got the same compilation times).
+ #if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
+ defined(BOOST_CONTRACT_STATIC_LINK)
+ BOOST_CONTRACT_DETAIL_DECL_DETAIL_COND_SUBCONTRACTING_Z(1,
+ /* is_friend = */ 1, OO, RR, FF, CC, AArgs);
+
+ BOOST_CONTRACT_DETAIL_DECL_FRIEND_OVERRIDING_PUBLIC_FUNCTIONS_Z(1,
+ OO, RR, FF, CC, AArgs, vv, rr, ff, oobj, aargs)
+ #endif
+ #ifndef BOOST_CONTRACT_NO_INVARIANTS
+ template<typename RR, class CC>
+ friend class boost::contract::detail::cond_inv;
+ #endif
+/** @endcond */
+};
+
+} } // namespace
+
+#endif // #include guard
+