Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:26

0001 
0002 #ifndef BOOST_CONTRACT_DETAIL_COND_INV_HPP_
0003 #define BOOST_CONTRACT_DETAIL_COND_INV_HPP_
0004 
0005 // Copyright (C) 2008-2018 Lorenzo Caminiti
0006 // Distributed under the Boost Software License, Version 1.0 (see accompanying
0007 // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
0008 // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
0009 
0010 #include <boost/contract/core/exception.hpp>
0011 #include <boost/contract/core/config.hpp>
0012 #include <boost/contract/detail/condition/cond_post.hpp>
0013 #ifndef BOOST_CONTRACT_NO_INVARIANTS
0014     #include <boost/contract/core/access.hpp>
0015     #include <boost/type_traits/add_pointer.hpp>
0016     #include <boost/type_traits/is_volatile.hpp>
0017     #include <boost/mpl/vector.hpp>
0018     #include <boost/mpl/transform.hpp>
0019     #include <boost/mpl/for_each.hpp>
0020     #include <boost/mpl/copy_if.hpp>
0021     #include <boost/mpl/eval_if.hpp>
0022     #include <boost/mpl/not.hpp>
0023     #include <boost/mpl/and.hpp>
0024     #include <boost/mpl/placeholders.hpp>
0025     #include <boost/utility/enable_if.hpp>
0026     #ifndef BOOST_CONTRACT_PERMISSIVE
0027         #include <boost/function_types/property_tags.hpp>
0028         #include <boost/static_assert.hpp>
0029     #endif
0030 #endif
0031 
0032 namespace boost { namespace contract { namespace detail {
0033 
0034 template<typename VR, class C>
0035 class cond_inv : public cond_post<VR> { // Non-copyable base.
0036     #if     !defined(BOOST_CONTRACT_NO_INVARIANTS) && \
0037             !defined(BOOST_CONTRACT_PERMISSIVE)
0038         BOOST_STATIC_ASSERT_MSG(
0039             (!boost::contract::access::has_static_invariant_f<
0040                 C, void, boost::mpl:: vector<>
0041             >::value),
0042             "static invariant member function cannot be mutable "
0043             "(it must be static instead)"
0044         );
0045         BOOST_STATIC_ASSERT_MSG(
0046             (!boost::contract::access::has_static_invariant_f<
0047                 C, void, boost::mpl::vector<>,
0048                         boost::function_types::const_non_volatile
0049             >::value),
0050             "static invariant member function cannot be const qualified "
0051             "(it must be static instead)"
0052         );
0053         BOOST_STATIC_ASSERT_MSG(
0054             (!boost::contract::access::has_static_invariant_f<
0055                 C, void, boost::mpl::vector<>,
0056                         boost::function_types::volatile_non_const
0057             >::value),
0058             "static invariant member function cannot be volatile qualified "
0059             "(it must be static instead)"
0060         );
0061         BOOST_STATIC_ASSERT_MSG(
0062             (!boost::contract::access::has_static_invariant_f<
0063                 C, void, boost::mpl::vector<>,
0064                         boost::function_types::cv_qualified
0065             >::value),
0066             "static invariant member function cannot be const volatile "
0067             "qualified (it must be static instead)"
0068         );
0069 
0070         BOOST_STATIC_ASSERT_MSG(
0071             (!boost::contract::access::has_invariant_s<
0072                 C, void, boost::mpl::vector<>
0073             >::value),
0074             "non-static invariant member function cannot be static "
0075             "(it must be either const or const volatile qualified instead)"
0076         );
0077         BOOST_STATIC_ASSERT_MSG(
0078             (!boost::contract::access::has_invariant_f<
0079                 C, void, boost::mpl::vector<>,
0080                         boost::function_types::non_cv
0081             >::value),
0082             "non-static invariant member function cannot be mutable "
0083             "(it must be either const or const volatile qualified instead)"
0084         );
0085         BOOST_STATIC_ASSERT_MSG(
0086             (!boost::contract::access::has_invariant_f<
0087                 C, void, boost::mpl::vector<>,
0088                         boost::function_types::volatile_non_const
0089             >::value),
0090             "non-static invariant member function cannot be volatile qualified "
0091             "(it must be const or const volatile qualified instead)"
0092         );
0093     #endif
0094 
0095 public:
0096     // obj can be 0 for static member functions.
0097     explicit cond_inv(boost::contract::from from, C* obj) :
0098         cond_post<VR>(from)
0099         #ifndef BOOST_CONTRACT_NO_CONDITIONS
0100             , obj_(obj)
0101         #endif
0102     {}
0103     
0104 protected:
0105     #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
0106         void check_entry_inv() { check_inv(true, false, false); }
0107         void check_entry_static_inv() { check_inv(true, true, false); }
0108         void check_entry_all_inv() { check_inv(true, false, true); }
0109     #endif
0110     
0111     #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
0112         void check_exit_inv() { check_inv(false, false, false); }
0113         void check_exit_static_inv() { check_inv(false, true, false); }
0114         void check_exit_all_inv() { check_inv(false, false, true); }
0115     #endif
0116 
0117     #ifndef BOOST_CONTRACT_NO_CONDITIONS
0118         C* object() { return obj_; }
0119     #endif
0120 
0121 private:
0122     #ifndef BOOST_CONTRACT_NO_INVARIANTS
0123         // Static, cv, and const inv in that order as strongest qualifier first.
0124         void check_inv(bool on_entry, bool static_only, bool const_and_cv) {
0125             if(this->failed()) return;
0126             try {
0127                 // Static members only check static inv.
0128                 check_static_inv<C>();
0129                 if(!static_only) {
0130                     if(const_and_cv) {
0131                         check_cv_inv<C>();
0132                         check_const_inv<C>();
0133                     } else if(boost::is_volatile<C>::value) {
0134                         check_cv_inv<C>();
0135                     } else {
0136                         check_const_inv<C>();
0137                     }
0138                 }
0139             } catch(...) {
0140                 if(on_entry) {
0141                     this->fail(&boost::contract::entry_invariant_failure);
0142                 } else this->fail(&boost::contract::exit_invariant_failure);
0143             }
0144         }
0145         
0146         template<class C_>
0147         typename boost::disable_if<
0148                 boost::contract::access::has_const_invariant<C_> >::type
0149         check_const_inv() {}
0150         
0151         template<class C_>
0152         typename boost::enable_if<
0153                 boost::contract::access::has_const_invariant<C_> >::type
0154         check_const_inv() { boost::contract::access::const_invariant(obj_); }
0155         
0156         template<class C_>
0157         typename boost::disable_if<
0158                 boost::contract::access::has_cv_invariant<C_> >::type
0159         check_cv_inv() {}
0160 
0161         template<class C_>
0162         typename boost::enable_if<
0163                 boost::contract::access::has_cv_invariant<C_> >::type
0164         check_cv_inv() { boost::contract::access::cv_invariant(obj_); }
0165         
0166         template<class C_>
0167         typename boost::disable_if<
0168                 boost::contract::access::has_static_invariant<C_> >::type
0169         check_static_inv() {}
0170         
0171         template<class C_>
0172         typename boost::enable_if<
0173                 boost::contract::access::has_static_invariant<C_> >::type
0174         check_static_inv() {
0175             // SFINAE HAS_STATIC_... returns true even when member is inherited
0176             // so extra run-time check here (not the same for non static).
0177             if(!inherited<boost::contract::access::has_static_invariant,
0178                     boost::contract::access::static_invariant_addr>::apply()) {
0179                 boost::contract::access::static_invariant<C_>();
0180             }
0181         }
0182 
0183         // Check if class's func is inherited from its base types or not.
0184         template<template<class> class HasFunc, template<class> class FuncAddr>
0185         struct inherited {
0186             static bool apply() {
0187                 try {
0188                     boost::mpl::for_each<
0189                         // For now, no reason to deeply search inheritance tree
0190                         // (SFINAE HAS_STATIC_... already fails in that case).
0191                         typename boost::mpl::transform<
0192                             typename boost::mpl::copy_if<
0193                                 typename boost::mpl::eval_if<boost::contract::
0194                                         access::has_base_types<C>,
0195                                     typename boost::contract::access::
0196                                             base_types_of<C>
0197                                 ,
0198                                     boost::mpl::vector<>
0199                                 >::type,
0200                                 HasFunc<boost::mpl::_1>
0201                             >::type,
0202                             boost::add_pointer<boost::mpl::_1>
0203                         >::type
0204                     >(compare_func_addr());
0205                 } catch(signal_equal const&) { return true; }
0206                 return false;
0207             }
0208 
0209         private:
0210             class signal_equal {}; // Except. to stop for_each as soon as found.
0211 
0212             struct compare_func_addr {
0213                 template<typename B>
0214                 void operator()(B*) {
0215                     // Inherited func has same addr as in its base.
0216                     if(FuncAddr<C>::apply() == FuncAddr<B>::apply()) {
0217                         throw signal_equal();
0218                     }
0219                 }
0220             };
0221         };
0222     #endif
0223 
0224     #ifndef BOOST_CONTRACT_NO_CONDITIONS
0225         C* obj_;
0226     #endif
0227 };
0228 
0229 } } } // namespace
0230 
0231 #endif // #include guard
0232