diff --git a/include/boost/contract/ext_/preprocessor/traits/adt.hpp b/include/boost/contract/ext_/preprocessor/traits/adt.hpp index 0c1bcba..7c48470 100644 --- a/include/boost/contract/ext_/preprocessor/traits/adt.hpp +++ b/include/boost/contract/ext_/preprocessor/traits/adt.hpp @@ -3,6 +3,7 @@ #define BOOST_CONTRACT_EXT_PP_TRAITS_ADT_HPP_ #include +#include #include #include @@ -44,11 +45,13 @@ // NOTE: Using `BOOST_PP_TUPLE_ELEM(2, 0, sign_traits)` confuses MSVC here. #define BOOST_CONTRACT_EXT_PP_SIGN_TRAITS_FIRST(sign_traits) \ - BOOST_CONTRACT_EXT_PP_SIGN_TRAITS_FIRST_ sign_traits + BOOST_CONTRACT_EXT_PP_EXPAND1( \ + BOOST_CONTRACT_EXT_PP_SIGN_TRAITS_FIRST_ sign_traits) // NOTE: Using `BOOST_PP_TUPLE_ELEM(2, 1, sign_traits)` confuses MSVC here. #define BOOST_CONTRACT_EXT_PP_SIGN_TRAITS_SECOND(sign_traits) \ - BOOST_CONTRACT_EXT_PP_SIGN_TRAITS_SECOND_ sign_traits + BOOST_CONTRACT_EXT_PP_EXPAND1( \ + BOOST_CONTRACT_EXT_PP_SIGN_TRAITS_SECOND_ sign_traits) #endif // #include guard diff --git a/include/boost/contract/ext_/preprocessor/traits/tparam/kind.hpp b/include/boost/contract/ext_/preprocessor/traits/tparam/kind.hpp index b8f0463..d0d979b 100644 --- a/include/boost/contract/ext_/preprocessor/traits/tparam/kind.hpp +++ b/include/boost/contract/ext_/preprocessor/traits/tparam/kind.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -43,8 +44,11 @@ #define BOOST_CONTRACT_EXT_PP_TPARAM_TRAITS_KIND_PARSE(sign_traits) \ ( \ - BOOST_CONTRACT_EXT_PP_TPARAM_TRAITS_KIND_SIGN_ sign_traits, \ - BOOST_CONTRACT_EXT_PP_TPARAM_TRAITS_KIND_TRAIT_ sign_traits \ + BOOST_CONTRACT_EXT_PP_EXPAND1( \ + BOOST_CONTRACT_EXT_PP_TPARAM_TRAITS_KIND_SIGN_ sign_traits) \ + , \ + BOOST_CONTRACT_EXT_PP_EXPAND1( \ + BOOST_CONTRACT_EXT_PP_TPARAM_TRAITS_KIND_TRAIT_ sign_traits) \ ) // Expand to `typename | class | (,,,) | template( ,,, ) class` (for type, diff --git a/include/boost/contract/ext_/preprocessor/utility/expand.hpp b/include/boost/contract/ext_/preprocessor/utility/expand.hpp new file mode 100644 index 0000000..eace65b --- /dev/null +++ b/include/boost/contract/ext_/preprocessor/utility/expand.hpp @@ -0,0 +1,18 @@ + +#ifndef BOOST_CONTRACT_EXT_PP_EXPAND_HPP_ +#define BOOST_CONTRACT_EXT_PP_EXPAND_HPP_ + +/* PUBLIC */ + +// Expand its argument once, `BOOST_PP_EXPAND` expands twice instead: +// EXPAND1(x) --> x (x expanded once) +// EXPAND(x) --> EXPAND_(x) --> x (x expanded twice) +// NOTE: This macro is sometimes useful to enforce proper macro expansion on +// MSVC (on better preprocessors like GCC, CLang, and Wave this macro is not +// necessary instead). For example, `EXPAND1(macro args) ...` where `args` is +// `(a, b EMPTY)` expands to `macro(a, b EMPTY) ...`, otherwise MSVc would +// sometimes confuse `...` as arguments for `EMPTY`. +#define BOOST_CONTRACT_EXT_PP_EXPAND1(tokens) tokens + +#endif // #include gaurd + diff --git a/test/aux_/pp_traits.hpp b/test/aux_/pp_traits.hpp index 2b30ae1..72372ed 100644 --- a/test/aux_/pp_traits.hpp +++ b/test/aux_/pp_traits.hpp @@ -95,6 +95,7 @@ std::string trim ( std::string const& source ) { sign_after_trait, \ parsed_trait \ ) \ + "#undefine DEBUG macro `-DDEBUG` for full generated C++ code instead" \ sign = sign_before_trait sign_at_trait sign_after_trait \ --> \ (remaining_sign, BOOST_PP_NIL parsed_traits) = parse_traits_macro( \ diff --git a/test/pp_func_traits/template.cpp b/test/pp_func_traits/template.cpp index 0b5a8ed..56e2582 100644 --- a/test/pp_func_traits/template.cpp +++ b/test/pp_func_traits/template.cpp @@ -25,9 +25,11 @@ // from the parsed trait to check if the parsing was correct. But, at the end // these are valuable tests also because they use the TPARAM_TRAITS macros. -// Assume all 1-tuple types were specified without parenthesis in these tests -// (in real code generation this is not an issue, but here generated code must -// match original signature and its parenthesis). +// Assume all 1-tuple types were specified without parenthesis. This is usually +// NOT true, but it is true in these tests. This is relevant only in these +// tests where generated code must match original signature and its parenthesis +// (the extra parenthesis of the original signature do not need to be +// reproduced when generating C++ code so this assumption is not necessary). #define BOOST_CONTRACT_TEST_TPARAM_REM_YES_(tokens) \ BOOST_PP_EXPR_IIF(BOOST_PP_EQUAL(BOOST_PP_TUPLE_SIZE(tokens), 1), \ BOOST_PP_TUPLE_REM(0) \ @@ -80,22 +82,8 @@ trait \ ) - //BOOST_CONTRACT_EXT_PP_TRAITS_AUX_TYPE_PARSE( int I BOOST_PP_EMPTY ) - // - //BOOST_CONTRACT_EXT_PP_TRAITS_AUX_TYPE_PARSE( unsigned long unsigned long const I BOOST_PP_EMPTY ) - // - //BOOST_CONTRACT_EXT_PP_TRAITS_AUX_TYPE_PARSE( (int const* const) I BOOST_PP_EMPTY ) - // - //BOOST_CONTRACT_EXT_PP_TRAITS_AUX_TYPE_PARSE( (::std::map) I BOOST_PP_EMPTY ) - // - //BOOST_CONTRACT_EXT_PP_TRAITS_AUX_TYPE_PARSE( auto I BOOST_PP_EMPTY ) - // - //BOOST_CONTRACT_EXT_PP_TRAITS_AUX_TYPE_PARSE( register unsigned int const I BOOST_PP_EMPTY ) - // - //BOOST_CONTRACT_EXT_PP_TRAITS_AUX_TYPE_PARSE( unsigned decltype(std::map::value_type() + 1) const I BOOST_PP_EMPTY ) - int main ( ) { -/* // Test no template. + // Test no template. BOOST_CONTRACT_TEST_( BOOST_PP_EMPTY() ) // Test template with no parameter. @@ -137,23 +125,17 @@ int main ( ) { BOOST_CONTRACT_TEST_( template( int ) ) // Test unnamed value with default. BOOST_CONTRACT_TEST_( template( int, default 123 ) ) -*/ - - BOOST_CONTRACT_EXT_PP_TRAITS_AUX_TYPE( - (std::map::key_type) I ) // Test named value (of parenthesized type). - BOOST_CONTRACT_TEST_( template( int I ) ) - BOOST_CONTRACT_TEST_( template( (std::map::key_type) I ) ) // Test named value (of parenthesized type) with default. - //BOOST_CONTRACT_TEST_( - // template( (std::map::key_type) I, default 123 ) ) + BOOST_CONTRACT_TEST_( + template( (std::map::key_type) I, default 123 ) ) // Test unnamed value (of parenthesized type). - //BOOST_CONTRACT_TEST_( template( (std::map::key_type) ) ) + BOOST_CONTRACT_TEST_( template( (std::map::key_type) ) ) // Test unnamed value (of parenthesized type) with default. - //BOOST_CONTRACT_TEST_( - // template( (std::map::key_type), default 123 ) ) + BOOST_CONTRACT_TEST_( + template( (std::map::key_type), default 123 ) ) /* // Test template-template parameter with no parameters. //BOOST_CONTRACT_TEST_( template( template( ) class P ) )