123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- #ifndef BOOST_CONTRACT_BASE_TYPES_HPP_
- #define BOOST_CONTRACT_BASE_TYPES_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 inheritance form base classes (for subcontracting).
- */
- // IMPORTANT: Included by contract_macro.hpp so must #if-guard all its includes.
- #include <boost/contract/core/config.hpp>
- #include <boost/preprocessor/config/config.hpp>
- #ifdef BOOST_CONTRACT_DETAIL_DOXYGEN
- /**
- Used to program the @c typedef that lists the bases of a derived class.
- In order to support subcontracting, a derived class that specifies contracts for
- one or more overriding public functions must declare a @c typedef named
- @c base_types (or @RefMacro{BOOST_CONTRACT_BASES_TYPEDEF}) using this macro:
- @code
- class u
- #define BASES public b, protected virtual w1, private w2
- : BASES
- {
- friend class boost::contract:access;
- typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
- #undef BASES
- ...
- };
- @endcode
- This @c typedef must be @c public unless @RefClass{boost::contract::access} is
- used.
- @see @RefSect{tutorial.base_classes__subcontracting_, Base Classes}
- @param ... Comma separated list of base classes.
- Each base must explicitly specify its access specifier @c public,
- @c protected, or @c private, and also @c virtual when present
- (this not always required in C++ instead).
- There is a limit of about 20 maximum bases that can be listed
- (because of similar limits in Boost.MPL internally used by this
- library).
- This is a variadic macro parameter, on compilers that do not support
- variadic macros, the @c typedef for base classes can be programmed
- manually without using this macro (see
- @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}).
-
- */
- #define BOOST_CONTRACT_BASE_TYPES(...)
- #elif !BOOST_PP_VARIADICS
-
- #define BOOST_CONTRACT_BASE_TYPES \
- BOOST_CONTRACT_ERROR_macro_BASE_TYPES_requires_variadic_macros_otherwise_manually_program_base_types
- #elif !defined(BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS)
- #include <boost/mpl/vector.hpp>
- #include <boost/contract/detail/preprocessor/keyword/virtual.hpp>
- #include <boost/contract/detail/preprocessor/keyword/public.hpp>
- #include <boost/contract/detail/preprocessor/keyword/protected.hpp>
- #include <boost/contract/detail/preprocessor/keyword/private.hpp>
- #include <boost/preprocessor/variadic/to_seq.hpp>
- #include <boost/preprocessor/seq/fold_left.hpp>
- #include <boost/preprocessor/seq/enum.hpp>
- #include <boost/preprocessor/seq/push_back.hpp>
- #include <boost/preprocessor/seq/size.hpp>
- #include <boost/preprocessor/seq/seq.hpp> // For HEAD, TAIL, etc.
- #include <boost/preprocessor/tuple/elem.hpp>
- #include <boost/preprocessor/tuple/rem.hpp>
- #include <boost/preprocessor/tuple/eat.hpp>
- #include <boost/preprocessor/comparison/equal.hpp>
- #include <boost/preprocessor/control/iif.hpp>
- #include <boost/preprocessor/facilities/expand.hpp>
- /* PRIVATE */
- #define BOOST_CONTRACT_BASE_TYPES_REMOVE_VIRTUAL_(base) \
- BOOST_PP_EXPAND( \
- BOOST_PP_IIF(BOOST_CONTRACT_DETAIL_PP_KEYWORD_IS_VIRTUAL(base), \
- BOOST_CONTRACT_DETAIL_PP_KEYWORD_REMOVE_VIRTUAL \
- , \
- BOOST_PP_TUPLE_REM(1) \
- )(base) \
- )
- #define BOOST_CONTRACT_BASE_TYPES_PUSH_BACK_IF_(is_public, types_nilseq, base) \
- ( \
- is_public, \
- BOOST_PP_IIF(is_public, \
- BOOST_PP_SEQ_PUSH_BACK \
- , \
- types_nilseq BOOST_PP_TUPLE_EAT(2) \
- )(types_nilseq, base) \
- )
- #define BOOST_CONTRACT_BASE_TYPES_SKIP_NOT_PUBLIC_(is_public, types_nilseq, \
- base) \
- (0, types_nilseq)
- // Precondition: base = `public [virtual] ...`.
- #define BOOST_CONTRACT_BASE_TYPES_PUSH_BACK_PUBLIC_(is_public, types_nilseq, \
- base) \
- ( \
- 1, \
- BOOST_PP_SEQ_PUSH_BACK(types_nilseq, \
- BOOST_CONTRACT_BASE_TYPES_REMOVE_VIRTUAL_( \
- BOOST_CONTRACT_DETAIL_PP_KEYWORD_REMOVE_PUBLIC(base)) \
- ) \
- )
- #define BOOST_CONTRACT_BASE_TYPES_ACCESS_(is_public, types_nilseq, base) \
- BOOST_PP_IIF(BOOST_CONTRACT_DETAIL_PP_KEYWORD_IS_PUBLIC(base), \
- BOOST_CONTRACT_BASE_TYPES_PUSH_BACK_PUBLIC_ \
- , BOOST_PP_IIF(BOOST_CONTRACT_DETAIL_PP_KEYWORD_IS_PROTECTED(base), \
- BOOST_CONTRACT_BASE_TYPES_SKIP_NOT_PUBLIC_ \
- , BOOST_PP_IIF(BOOST_CONTRACT_DETAIL_PP_KEYWORD_IS_PRIVATE(base), \
- BOOST_CONTRACT_BASE_TYPES_SKIP_NOT_PUBLIC_ \
- , \
- BOOST_CONTRACT_BASE_TYPES_PUSH_BACK_IF_ \
- )))(is_public, types_nilseq, base)
- #define BOOST_CONTRACT_BASE_TYPES_(s, public_types, base) \
- BOOST_CONTRACT_BASE_TYPES_ACCESS_( \
- BOOST_PP_TUPLE_ELEM(2, 0, public_types), \
- BOOST_PP_TUPLE_ELEM(2, 1, public_types), \
- BOOST_CONTRACT_BASE_TYPES_REMOVE_VIRTUAL_(base) \
- )
- #define BOOST_CONTRACT_BASE_TYPES_RETURN_YES_(types_nilseq) \
- BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TAIL(types_nilseq))
- #define BOOST_CONTRACT_BASE_TYPES_RETURN_(types_nilseq) \
- BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_SEQ_SIZE(types_nilseq), 1), \
- BOOST_PP_TUPLE_EAT(1) \
- , \
- BOOST_CONTRACT_BASE_TYPES_RETURN_YES_ \
- )(types_nilseq)
- #define BOOST_CONTRACT_BASE_TYPES_OK_(base_tuple, bases_seq) \
- boost::mpl::vector< \
- BOOST_CONTRACT_BASE_TYPES_RETURN_(BOOST_PP_TUPLE_ELEM(2, 1, \
- BOOST_PP_SEQ_FOLD_LEFT( \
- BOOST_CONTRACT_BASE_TYPES_, \
- (0, (BOOST_PP_NIL)), \
- bases_seq \
- ) \
- )) \
- >
- #define BOOST_CONTRACT_BASE_TYPES_ERR_(bases_tuple, bases_seq) \
- BOOST_CONTRACT_ERROR_all_bases_must_explicitly_specify_public_protected_or_private base_tuple
- #define BOOST_CONTRACT_BASE_TYPES_IS_ACCESS_(base) \
- BOOST_PP_IIF(BOOST_CONTRACT_DETAIL_PP_KEYWORD_IS_PUBLIC(base), \
- 1 \
- , BOOST_PP_IIF(BOOST_CONTRACT_DETAIL_PP_KEYWORD_IS_PROTECTED(base), \
- 1 \
- , BOOST_PP_IIF(BOOST_CONTRACT_DETAIL_PP_KEYWORD_IS_PRIVATE(base), \
- 1 \
- , \
- 0 \
- )))
- // Cannot check that all base types have access specifiers (unless users have to
- // specify bases using pp-seq, because user specified base list can have
- // unwrapped commas between bases but also within a given base type, when base
- // types are templates), but at least check the very first base type explicitly
- // specifies access `[virtual] public | protected | private [virtual] ...`.
- #define BOOST_CONTRACT_BASE_TYPES_CHECK_(bases_tuple, bases_seq) \
- BOOST_PP_IIF(BOOST_CONTRACT_BASE_TYPES_IS_ACCESS_( \
- BOOST_CONTRACT_BASE_TYPES_REMOVE_VIRTUAL_(BOOST_PP_SEQ_HEAD( \
- bases_seq))), \
- BOOST_CONTRACT_BASE_TYPES_OK_ \
- , \
- BOOST_CONTRACT_BASE_TYPES_ERR_ \
- )(bases_tuple, bases_seq)
- /* PUBLIC */
- #define BOOST_CONTRACT_BASE_TYPES(...) \
- BOOST_CONTRACT_BASE_TYPES_CHECK_((__VA_ARGS__), \
- BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
- #else
- #define BOOST_CONTRACT_BASE_TYPES(...) void /* dummy type for typedef */
- #endif
- #endif // #include guard
|