1 2 #ifndef BOOST_CONTRACT_BASE_TYPES_HPP_ 3 #define BOOST_CONTRACT_BASE_TYPES_HPP_ 4 5 // Copyright (C) 2008-2018 Lorenzo Caminiti 6 // Distributed under the Boost Software License, Version 1.0 (see accompanying 7 // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). 8 // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html 9 10 /** @file 11 Specify inheritance form base classes (for subcontracting). 12 */ 13 14 // IMPORTANT: Included by contract_macro.hpp so must #if-guard all its includes. 15 #include <boost/contract/core/config.hpp> 16 #include <boost/preprocessor/config/config.hpp> 17 18 #ifdef BOOST_CONTRACT_DETAIL_DOXYGEN 19 20 /** 21 Used to program the @c typedef that lists the bases of a derived class. 22 23 In order to support subcontracting, a derived class that specifies contracts for 24 one or more overriding public functions must declare a @c typedef named 25 @c base_types (or @RefMacro{BOOST_CONTRACT_BASES_TYPEDEF}) using this macro: 26 27 @code 28 class u 29 #define BASES public b, protected virtual w1, private w2 30 : BASES 31 { 32 friend class boost::contract:access; 33 34 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; 35 #undef BASES 36 37 ... 38 }; 39 @endcode 40 41 This @c typedef must be @c public unless @RefClass{boost::contract::access} is 42 used. 43 44 @see @RefSect{tutorial.base_classes__subcontracting_, Base Classes} 45 46 @param ... Comma separated list of base classes. 47 Each base must explicitly specify its access specifier @c public, 48 @c protected, or @c private, and also @c virtual when present 49 (this not always required in C++ instead). 50 There is a limit of about 20 maximum bases that can be listed 51 (because of similar limits in Boost.MPL internally used by this 52 library). 53 This is a variadic macro parameter, on compilers that do not support 54 variadic macros, the @c typedef for base classes can be programmed 55 manually without using this macro (see 56 @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}). 57 58 */ 59 #define BOOST_CONTRACT_BASE_TYPES(...) 60 61 #elif !BOOST_PP_VARIADICS 62 63 #define BOOST_CONTRACT_BASE_TYPES \ 64 BOOST_CONTRACT_ERROR_macro_BASE_TYPES_requires_variadic_macros_otherwise_manually_program_base_types 65 66 #elif !defined(BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS) 67 68 #include <boost/mpl/vector.hpp> 69 #include <boost/contract/detail/preprocessor/keyword/virtual.hpp> 70 #include <boost/contract/detail/preprocessor/keyword/public.hpp> 71 #include <boost/contract/detail/preprocessor/keyword/protected.hpp> 72 #include <boost/contract/detail/preprocessor/keyword/private.hpp> 73 #include <boost/preprocessor/variadic/to_seq.hpp> 74 #include <boost/preprocessor/seq/fold_left.hpp> 75 #include <boost/preprocessor/seq/enum.hpp> 76 #include <boost/preprocessor/seq/push_back.hpp> 77 #include <boost/preprocessor/seq/size.hpp> 78 #include <boost/preprocessor/seq/seq.hpp> // For HEAD, TAIL, etc. 79 #include <boost/preprocessor/tuple/elem.hpp> 80 #include <boost/preprocessor/tuple/rem.hpp> 81 #include <boost/preprocessor/tuple/eat.hpp> 82 #include <boost/preprocessor/comparison/equal.hpp> 83 #include <boost/preprocessor/control/iif.hpp> 84 #include <boost/preprocessor/facilities/expand.hpp> 85 86 /* PRIVATE */ 87 88 #define BOOST_CONTRACT_BASE_TYPES_REMOVE_VIRTUAL_(base) \ 89 BOOST_PP_EXPAND( \ 90 BOOST_PP_IIF(BOOST_CONTRACT_DETAIL_PP_KEYWORD_IS_VIRTUAL(base), \ 91 BOOST_CONTRACT_DETAIL_PP_KEYWORD_REMOVE_VIRTUAL \ 92 , \ 93 BOOST_PP_TUPLE_REM(1) \ 94 )(base) \ 95 ) 96 97 #define BOOST_CONTRACT_BASE_TYPES_PUSH_BACK_IF_(is_public, types_nilseq, base) \ 98 ( \ 99 is_public, \ 100 BOOST_PP_IIF(is_public, \ 101 BOOST_PP_SEQ_PUSH_BACK \ 102 , \ 103 types_nilseq BOOST_PP_TUPLE_EAT(2) \ 104 )(types_nilseq, base) \ 105 ) 106 107 #define BOOST_CONTRACT_BASE_TYPES_SKIP_NOT_PUBLIC_(is_public, types_nilseq, \ 108 base) \ 109 (0, types_nilseq) 110 111 // Precondition: base = `public [virtual] ...`. 112 #define BOOST_CONTRACT_BASE_TYPES_PUSH_BACK_PUBLIC_(is_public, types_nilseq, \ 113 base) \ 114 ( \ 115 1, \ 116 BOOST_PP_SEQ_PUSH_BACK(types_nilseq, \ 117 BOOST_CONTRACT_BASE_TYPES_REMOVE_VIRTUAL_( \ 118 BOOST_CONTRACT_DETAIL_PP_KEYWORD_REMOVE_PUBLIC(base)) \ 119 ) \ 120 ) 121 122 #define BOOST_CONTRACT_BASE_TYPES_ACCESS_(is_public, types_nilseq, base) \ 123 BOOST_PP_IIF(BOOST_CONTRACT_DETAIL_PP_KEYWORD_IS_PUBLIC(base), \ 124 BOOST_CONTRACT_BASE_TYPES_PUSH_BACK_PUBLIC_ \ 125 , BOOST_PP_IIF(BOOST_CONTRACT_DETAIL_PP_KEYWORD_IS_PROTECTED(base), \ 126 BOOST_CONTRACT_BASE_TYPES_SKIP_NOT_PUBLIC_ \ 127 , BOOST_PP_IIF(BOOST_CONTRACT_DETAIL_PP_KEYWORD_IS_PRIVATE(base), \ 128 BOOST_CONTRACT_BASE_TYPES_SKIP_NOT_PUBLIC_ \ 129 , \ 130 BOOST_CONTRACT_BASE_TYPES_PUSH_BACK_IF_ \ 131 )))(is_public, types_nilseq, base) 132 133 #define BOOST_CONTRACT_BASE_TYPES_(s, public_types, base) \ 134 BOOST_CONTRACT_BASE_TYPES_ACCESS_( \ 135 BOOST_PP_TUPLE_ELEM(2, 0, public_types), \ 136 BOOST_PP_TUPLE_ELEM(2, 1, public_types), \ 137 BOOST_CONTRACT_BASE_TYPES_REMOVE_VIRTUAL_(base) \ 138 ) 139 140 #define BOOST_CONTRACT_BASE_TYPES_RETURN_YES_(types_nilseq) \ 141 BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TAIL(types_nilseq)) 142 143 #define BOOST_CONTRACT_BASE_TYPES_RETURN_(types_nilseq) \ 144 BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_SEQ_SIZE(types_nilseq), 1), \ 145 BOOST_PP_TUPLE_EAT(1) \ 146 , \ 147 BOOST_CONTRACT_BASE_TYPES_RETURN_YES_ \ 148 )(types_nilseq) 149 150 #define BOOST_CONTRACT_BASE_TYPES_OK_(base_tuple, bases_seq) \ 151 boost::mpl::vector< \ 152 BOOST_CONTRACT_BASE_TYPES_RETURN_(BOOST_PP_TUPLE_ELEM(2, 1, \ 153 BOOST_PP_SEQ_FOLD_LEFT( \ 154 BOOST_CONTRACT_BASE_TYPES_, \ 155 (0, (BOOST_PP_NIL)), \ 156 bases_seq \ 157 ) \ 158 )) \ 159 > 160 161 #define BOOST_CONTRACT_BASE_TYPES_ERR_(bases_tuple, bases_seq) \ 162 BOOST_CONTRACT_ERROR_all_bases_must_explicitly_specify_public_protected_or_private base_tuple 163 164 #define BOOST_CONTRACT_BASE_TYPES_IS_ACCESS_(base) \ 165 BOOST_PP_IIF(BOOST_CONTRACT_DETAIL_PP_KEYWORD_IS_PUBLIC(base), \ 166 1 \ 167 , BOOST_PP_IIF(BOOST_CONTRACT_DETAIL_PP_KEYWORD_IS_PROTECTED(base), \ 168 1 \ 169 , BOOST_PP_IIF(BOOST_CONTRACT_DETAIL_PP_KEYWORD_IS_PRIVATE(base), \ 170 1 \ 171 , \ 172 0 \ 173 ))) 174 175 // Cannot check that all base types have access specifiers (unless users have to 176 // specify bases using pp-seq, because user specified base list can have 177 // unwrapped commas between bases but also within a given base type, when base 178 // types are templates), but at least check the very first base type explicitly 179 // specifies access `[virtual] public | protected | private [virtual] ...`. 180 #define BOOST_CONTRACT_BASE_TYPES_CHECK_(bases_tuple, bases_seq) \ 181 BOOST_PP_IIF(BOOST_CONTRACT_BASE_TYPES_IS_ACCESS_( \ 182 BOOST_CONTRACT_BASE_TYPES_REMOVE_VIRTUAL_(BOOST_PP_SEQ_HEAD( \ 183 bases_seq))), \ 184 BOOST_CONTRACT_BASE_TYPES_OK_ \ 185 , \ 186 BOOST_CONTRACT_BASE_TYPES_ERR_ \ 187 )(bases_tuple, bases_seq) 188 189 /* PUBLIC */ 190 191 #define BOOST_CONTRACT_BASE_TYPES(...) \ 192 BOOST_CONTRACT_BASE_TYPES_CHECK_((__VA_ARGS__), \ 193 BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) 194 195 #else 196 197 #define BOOST_CONTRACT_BASE_TYPES(...) void /* dummy type for typedef */ 198 199 #endif 200 201 #endif // #include guard 202 203