#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 #include #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 #include #include #include #include #include #include #include #include #include #include // For HEAD, TAIL, etc. #include #include #include #include #include #include /* 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