diff --git a/doc/qbk/grammar.qbk b/doc/qbk/grammar.qbk index b495ce2..1235e9c 100644 --- a/doc/qbk/grammar.qbk +++ b/doc/qbk/grammar.qbk @@ -5,6 +5,12 @@ [/ http://www.boost.org/LICENSE_1_0.txt) ] [/ Home at http://sourceforge.net/projects/contractpp ] +[def __typedef_declaration__ [link typedef_declaration_anchor [^['typedef-declaration]]]] +[def __using_alias__ [link using_alias_anchor [^['using-alias]]]] +[def __using_declaration__ [link using_declaration_anchor [^['using-declaration]]]] +[def __static_select_assertion__ [link static_select_assertion_anchor [^['static-select-assertion]]]] +[def __alias__ [link alias_anchor [^['alias]]]] +[def __auto_type__ [link auto_type [^['auto-type]]]] [def __assertion__ [link assertion_anchor [^['assertion]]]] [def __assertion_condition__ [link assertion_condition_anchor [^['assertion-condition]]]] [def __assertion_expression__ [link assertion_expression_anchor [^['assertion-expression]]]] @@ -54,6 +60,10 @@ [def __type_qualifier__ [link type_qualifier_anchor [^['type-qualifier]]]] [def __wrapped_type__ [link wrapped_type_anchor [^['wrapped-type]]]] +[def __capture_boolean_expression__ [link capture_boolean_expression_anchor [^[*capture-boolean-expression]]]] +[def __capture__ [link capture_anchor [^[*capture]]]] +[def __name__ [link name_anchor [^[*name]]]] +[def __new_name__ [link new_name_anchor [^[*new-name]]]] [def __boolean_expression__ [link boolean_expression_anchor [^[*boolean-expression]]]] [def __boolean_expression_of_inscope_variables__ [link boolean_expression_of_inscope_variables_anchor [^[*boolean-expression-of-inscope-variables]]]] [def __boost_concept__ [link boost_concept_anchor [^[*boost-concept]]]] @@ -366,6 +376,9 @@ Note that when specified, `virtual` must appear after the inheritance access lev __fundamental_type__``/:/ [#fundamental_type_anchor]`` ``/{/``const ``/|/`` volatile ``/|/`` long ``/|/`` short ``/|/`` signed ``/|/`` unsigned ``/|/`` void ``/|/`` bool ``/|/`` char ``/|/`` char16_t ``/|/`` char32_t ``/|/`` double ``/|/`` float ``/|/`` int ``/|/`` wchar_t``/}+/`` + + __auto_type__``/:/ [#auto_type_anchor]`` + __wrapped_type__ ``/|/`` auto This is the syntax used to specify types of different entities such as the function return type, the function parameter types, the types of value template parameters, etc. The usual constraints of C++ for qualified fundamental type apply (it invalid to specify `int int`, `long int long`, `unsigned void`, etc). @@ -410,7 +423,7 @@ This library cannot automatically perform such a promotion so the `static` speci [section Return Type] __return_type__``/:/ [#return_type_anchor]`` - __wrapped_type__ ``/|/`` auto + __auto_type__ As always with this syntax's wrapped types, note that fundamental types containing no symbol can be specified without extra parenthesis (`void`, `bool`, `int`, `unsigned long const`, `decltype(...)`, etc.). @@ -513,6 +526,76 @@ Exception specifications apply only to exceptions thrown by the function body an [endsect] +[section Assertions] + + __assertions__``/:/`` + ``/[/``__assertion__, ... ``/[/``,``/]/````/]/`` + +Note that an extra trailing comma `,` is always allowed here but never required (similarly to C++ trailing comma that can be used to end an enumeration declaration list). + + __assertion__``/:/`` + __alias__ ``/|/`` + + __auto_type__ __new_name__ = return ``/|/`` + __auto_type__ __new_name__ = ``[macroref CONTRACT_OLDOF]`` __oldof_expression__ ``/|/`` + + __boolean_condition__ ``/|/`` + + __select_assertion__ ``/|/`` + __static_select_assertion__ + +Where return and old-of declarations are allowed only within postconditions. + + __boolean_condition__``/:/`` + __boolean_expression__ ``/|/`` + const( ``/[/``__capture__, ...``/]/`` ) __capture_boolean_expression__ + +Parenthesis around __boolean_expression__ are always allowed here but they are actually required only when __boolean_expression__ starts with a non-alphanumeric symbol (e.g., `(!vector.empty())`) or it contains unwrapped commas `,`. +Parenthesis around __capture_boolean_expression__ are always allowed but they are actually required only when __capture_boolean_expression__ contains unwrapped commas `,`. + + __select_assertion__``/:/`` + if(__boolean_condition__) ( ``/[/``__assertion__, ...``/]/`` ) + ``/[/``else ( ``/[/``__assertion__, ...``/]/`` ) + + __static_select_assertion__``/:/`` + static if(__constant_boolean_expression__) ( ``/[/``__assertion__, ...``/]/`` ) + ``/[/``else ( ``/[/``__assertion__, ...``/]/`` ) + +For example, static select assertions can be used in generic programming to selectively check some assertions only when the types involved fulfill all operations required for the assertion checking. + +[endsect] + +[section Aliases] + + __alias__``/:/ [#alias_anchor]`` + __namespace_alias__ ``/|/`` __using_directive__ ``/|/`` __using_declaration__ ``/|/`` __using_alias__ ``/|/`` __typedef_declaration__ + + __namespace_alias__``/:/`` + namespace (__new_name__) as __name__ + + __using_directive__``/:/`` + using namespace __name__ + + __using_declaration__``/:/`` + using {``/[/``typename``/]/`` __name__ ``/|/`` (``/[/``typename``/]/`` __name__)} + + __using_alias__``/:/`` + ``/[/``template( ``/[/``__cxx_template_parameter__, ...``/]/`` )``/]/`` + using (__new_name__) as {__type__ | (__type__)} + + __typedef_declaration__``/:/`` + typedef __wrapped_type__ __new_name__ + +In __using_declaration__, parenthesis around __name__ are always allowed here but they are actually required only when __name__ contains unwrapped commas `,`. +As usual in C++, __name__ can be prefixed by `typename` if that it is needed to resolve dependent names. + +In __using_alias__, parenthesis around __type__ are always allowed here but they are actually required only when __type__ contains unwrapped commas `,`. + +For example, all the aliases above can be used to simplify and short types and names used to program assertions (aliases do not alter the run-time state of the program so they can be safely used to program assertions). + +[endsect] + + [section Preconditions] __assertions__``/:/ [#assertions_anchor]`` @@ -560,12 +643,6 @@ The type of the in-scope variable __inscope_variable__ is optional and it is aut [section Postconditions] - __oldof_assertions__``/:/ [#oldof_assertions_anchor]`` - ``/[/``__aliasing__``/, .../````/]/`` - ``/[/``auto __variable_name__ = return,``/]/`` - ``/{/``auto __variable_name__ = ``[macroref CONTRACT_OLDOF]`` __oldof_expression__,``/}*/`` - __assertion__``/, .../`` - If present, result and old value declarations should appear before any assertion because they will always be visible to all assertions, plus these declarations cannot be nested (within select-assertions, etc). The macro [macroref CONTRACT_OLDOF] allows but does not require parenthesis around the value expression __oldof_expression__, for example the following are both valid: diff --git a/include/boost/contract/ext_/preprocessor/keyword-generate.py b/include/boost/contract/ext_/preprocessor/keyword-generate.py index 50ea752..7e49f5f 100644 --- a/include/boost/contract/ext_/preprocessor/keyword-generate.py +++ b/include/boost/contract/ext_/preprocessor/keyword-generate.py @@ -108,7 +108,8 @@ entries = [ 'extends', 'verbatim', 'ref', - 'refref' + 'refref', + 'as' ] } ] diff --git a/include/boost/contract/ext_/preprocessor/keyword/contract/as.hpp b/include/boost/contract/ext_/preprocessor/keyword/contract/as.hpp new file mode 100644 index 0000000..4a2b87d --- /dev/null +++ b/include/boost/contract/ext_/preprocessor/keyword/contract/as.hpp @@ -0,0 +1,48 @@ + +#ifndef BOOST_CONTRACT_EXT_PP_KEYWORD_AS_HPP_ +#define BOOST_CONTRACT_EXT_PP_KEYWORD_AS_HPP_ + +// WARNING: FILE AUTOMATICALLY GENERATED, DO NOT MODIFY IT! +// Instead, modify and run related generation script "keyword-generate.py". + +#include +#include + +/* PRIVATE */ + +// Must expand to a single comma `,` (not local macros, do not #undefine). +#define BOOST_CONTRACT_EXT_PP_KEYWORD_AS_CAT_TO_COMMAas , +#define asBOOST_CONTRACT_EXT_PP_KEYWORD_AS_CAT_TO_COMMA , + +// Must expand to empty `` (not local macros, do not #undefine). +#define BOOST_CONTRACT_EXT_PP_KEYWORD_AS_CAT_TO_EMPTYas +#define asBOOST_CONTRACT_EXT_PP_KEYWORD_AS_CAT_TO_EMPTY + +/* PUBLIC */ + +// Precondition: tokens must start with a token concatenable to a macro name +// (e.g., a literal or integral token) or with parenthesis. +#define BOOST_CONTRACT_EXT_PP_KEYWORD_IS_AS_FRONT(tokens) \ + BOOST_CONTRACT_EXT_PP_KEYWORD_UTILITY_IS_FRONT( \ + BOOST_CONTRACT_EXT_PP_KEYWORD_AS_CAT_TO_COMMA, tokens) + +// Precondition: tokens must end with a token concatenable to a macro name +// (e.g., a literal or integral token) or with parenthesis. +#define BOOST_CONTRACT_EXT_PP_KEYWORD_IS_AS_BACK(tokens) \ + BOOST_CONTRACT_EXT_PP_KEYWORD_UTILITY_IS_BACK( \ + BOOST_CONTRACT_EXT_PP_KEYWORD_AS_CAT_TO_COMMA, tokens) + +// Precondition: tokens must start with `as` (this can be +// checked with `..._IS_AS_FRONT` macro above). +#define BOOST_CONTRACT_EXT_PP_KEYWORD_AS_REMOVE_FRONT(tokens) \ + BOOST_CONTRACT_EXT_PP_KEYWORD_UTILITY_REMOVE_FRONT( \ + BOOST_CONTRACT_EXT_PP_KEYWORD_AS_CAT_TO_EMPTY, tokens) + +// Precondition: tokens must end with `as` (this can be +// checked with `..._IS_AS_BACK` macro above). +#define BOOST_CONTRACT_EXT_PP_KEYWORD_AS_REMOVE_BACK(tokens) \ + BOOST_CONTRACT_EXT_PP_KEYWORD_UTILITY_REMOVE_BACK( \ + BOOST_CONTRACT_EXT_PP_KEYWORD_AS_CAT_TO_EMPTY, tokens) + +#endif // #include guard + diff --git a/include/boost/contract/ext_/preprocessor/traits/adt.hpp b/include/boost/contract/ext_/preprocessor/traits/adt.hpp index 27f1111..ffab680 100644 --- a/include/boost/contract/ext_/preprocessor/traits/adt.hpp +++ b/include/boost/contract/ext_/preprocessor/traits/adt.hpp @@ -37,7 +37,8 @@ // Declaration and traits (2-tuple). // Create a `decl_traits` data structure to start parsing specified declaration. -// Implementation: Leading NIL needed to handle empty macro params (on MSVC). +// Implementation: NIL in front of traits needed to handle empty macro params +// (on MSVC). #define BOOST_CONTRACT_EXT_PP_DECL_TRAITS_INIT(decl) (decl, BOOST_PP_NIL) // Expand to final traits after they have been parsed from declaration. diff --git a/include/boost/contract/ext_/preprocessor/traits/assertion/kind.hpp b/include/boost/contract/ext_/preprocessor/traits/assertion/kind.hpp new file mode 100644 index 0000000..fbd7dad --- /dev/null +++ b/include/boost/contract/ext_/preprocessor/traits/assertion/kind.hpp @@ -0,0 +1,23 @@ + +#ifndef BOOST_CONTRACT_EXT_PP_ASSERTION_TRAITS_KIND_HPP_ +#define BOOST_CONTRACT_EXT_PP_ASSERTION_TRAITS_KIND_HPP_ + +#include + +/* PUBLIC */ + +#define BOOST_CONTRACT_EXT_PP_ASSERTION_TRAITS_KIND_SET(kind, decl_traits) \ + ( \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_FIRST(decl_traits) \ + , \ + BOOST_CONTRACT_EXT_PP_TRAITS_PUSH_BACK( \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_SECOND(decl_traits), kind) \ + ) + +// Index 0 used and reserved for kind, other traits must use index 1, 2, etc. + +#define BOOST_CONTRACT_EXT_PP_ASSERTION_TRAITS_KIND(traits) \ + BOOST_CONTRACT_EXT_PP_TRAITS_ELEM(0, traits) + +#endif // #include guard + diff --git a/include/boost/contract/ext_/preprocessor/traits/assertion/namespace.hpp b/include/boost/contract/ext_/preprocessor/traits/assertion/namespace.hpp new file mode 100644 index 0000000..4e5b2dd --- /dev/null +++ b/include/boost/contract/ext_/preprocessor/traits/assertion/namespace.hpp @@ -0,0 +1,76 @@ + +#ifndef BOOST_CONTRACT_EXT_PP_NAMESPACE_ASSERTION_TRAITS_HPP_ +#define BOOST_CONTRACT_EXT_PP_NAMESPACE_ASSERTION_TRAITS_HPP_ + +#include +#include +#include +#include +#include +#include + +/* PUBLIC */ + +// Precondition: decl = `name`. +#define BOOST_CONTRACT_EXT_PP_NAMESPACE_ASSERTION_TRAITS_NAME_PARSE( \ + decl_traits) \ + ( \ + BOOST_PP_NIL \ + , \ + BOOST_CONTRACT_EXT_PP_TRAITS_PUSH_BACK( \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_SECOND(decl_traits), \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_FIRST(decl_traits) \ + ) \ + ) + +// NOTE: This extra macro is needed for proper expansion (on MSVC). +// Precondition: decl = `(new-name) as ...`. +#define BOOST_CONTRACT_EXT_PP_NAMESPACE_ASSERTION_TRAITS_REMOVE_PAREN_AS_(decl)\ + BOOST_CONTRACT_EXT_PP_KEYWORD_AS_REMOVE_FRONT(BOOST_PP_TUPLE_EAT(1) decl) + +// Precondition: decl = `namespace (new-name) as ...`. +#define BOOST_CONTRACT_EXT_PP_NAMESPACE_ASSERTION_TRAITS_NEW_NAME_PARSE( \ + decl_traits) \ + ( \ + BOOST_CONTRACT_EXT_PP_NAMESPACE_ASSERTION_TRAITS_REMOVE_PAREN_AS_( \ + BOOST_CONTRACT_EXT_PP_KEYWORD_NAMESPACE_REMOVE_FRONT( \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_FIRST( \ + decl_traits \ + ) \ + ) \ + ) \ + , \ + BOOST_CONTRACT_EXT_PP_TRAITS_PUSH_BACK( \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_SECOND(decl_traits), \ + BOOST_PP_TUPLE_REM_CTOR(1, \ + BOOST_CONTRACT_EXT_PP_PAREN_FRONT( \ + BOOST_CONTRACT_EXT_PP_KEYWORD_NAMESPACE_REMOVE_FRONT( \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_FIRST(decl_traits) \ + ) \ + ) \ + ) \ + ) \ + ) + +// decl = namespace (new-name) as name +#define BOOST_CONTRACT_EXT_PP_NAMESPACE_ASSERTION_TRAITS(decl) \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_DONE( \ + BOOST_CONTRACT_EXT_PP_NAMESPACE_ASSERTION_TRAITS_NAME_PARSE( \ + BOOST_CONTRACT_EXT_PP_NAMESPACE_ASSERTION_TRAITS_NEW_NAME_PARSE( \ + BOOST_CONTRACT_EXT_PP_ASSERTION_TRAITS_KIND_SET(namespace, \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_INIT( \ + decl \ + ))))) + +// Index 0 below already used and reserved for ASSERTION_TRAITS_KIND. + +// Expand to `token`. +#define BOOST_CONTRACT_EXT_PP_NAMESPACE_ASSERTION_TRAITS_NEW_NAME(traits) \ + BOOST_CONTRACT_EXT_PP_TRAITS_ELEM(1, traits) + +// Expand to `token`. +#define BOOST_CONTRACT_EXT_PP_NAMESPACE_ASSERTION_TRAITS_NAME(traits) \ + BOOST_CONTRACT_EXT_PP_TRAITS_ELEM(2, traits) + +#endif // #include guard + diff --git a/include/boost/contract/ext_/preprocessor/traits/assertion/typedef.hpp b/include/boost/contract/ext_/preprocessor/traits/assertion/typedef.hpp new file mode 100644 index 0000000..39d5307 --- /dev/null +++ b/include/boost/contract/ext_/preprocessor/traits/assertion/typedef.hpp @@ -0,0 +1,62 @@ + +#ifndef BOOST_CONTRACT_EXT_PP_TYPEDEF_ASSERTION_TRAITS_HPP_ +#define BOOST_CONTRACT_EXT_PP_TYPEDEF_ASSERTION_TRAITS_HPP_ + +/* PRIVATE */ + +#define BOOST_CONTRACT_EXT_PP_TYPEDEF_ASSERTION_TRAITS_NAME_PARSE_( \ + decl_type, traits) \ + ( \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_FIRST(decl_type) \ + , \ + BOOST_CONTRACT_EXT_PP_TRAITS_PUSH_BACK(traits, \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_SECOND(decl_type)) \ + ) + +/* PUBLIC */ + +// Precondition: decl = `new-name`. +#define BOOST_CONTRACT_EXT_PP_TYPEDEF_ASSERTION_TRAITS_NEW_NAME_PARSE( \ + decl_traits) \ + ( \ + BOOST_PP_NIL \ + , \ + BOOST_CONTRACT_EXT_PP_TRAITS_PUSH_BACK( \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_SECOND(decl_traits), \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_FIRST(decl_traits) \ + ) \ + ) + +// Precondition: decl = `typedef wrapped-type ...`. +#define BOOST_CONTRACT_EXT_PP_TYPEDEF_ASSERTION_TRAITS_NAME_PARSE(decl_traits) \ + BOOST_CONTRACT_EXT_PP_TYPEDEF_ASSERTION_TRAITS_NAME_PARSE_( \ + BOOST_CONTRACT_EXT_PP_TRAITS_AUX_TYPE( \ + BOOST_CONTRACT_EXT_PP_KEYWORD_TYPEDEF_REMOVE_FRONT( \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_FIRST(decl_traits) \ + ) \ + ), \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_SECOND(decl_traits) \ + ) + +// decl = typedef wrapped-type new-name +#define BOOST_CONTRACT_EXT_PP_TYPEDEF_ASSERTION_TRAITS(decl) \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_DONE( \ + BOOST_CONTRACT_EXT_PP_TYPEDEF_ASSERTION_TRAITS_NEW_NAME_PARSE( \ + BOOST_CONTRACT_EXT_PP_TYPEDEF_ASSERTION_TRAITS_NAME_PARSE( \ + BOOST_CONTRACT_EXT_PP_ASSERTION_TRAITS_KIND_SET(typedef, \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_INIT( \ + decl \ + ))))) + +// Index 0 below already used and reserved for ASSERTION_TRAITS_KIND. + +// Expand to `(,,,)`. +#define BOOST_CONTRACT_EXT_PP_TYPEDEF_ASSERTION_TRAITS_NAME(traits) \ + BOOST_CONTRACT_EXT_PP_TRAITS_ELEM(1, traits) + +// Expand to `token`. +#define BOOST_CONTRACT_EXT_PP_TYPEDEF_ASSERTION_TRAITS_NEW_NAME(traits) \ + BOOST_CONTRACT_EXT_PP_TRAITS_ELEM(2, traits) + +#endif // #include guard + diff --git a/include/boost/contract/ext_/preprocessor/traits/assertion/using.hpp b/include/boost/contract/ext_/preprocessor/traits/assertion/using.hpp new file mode 100644 index 0000000..ad20e99 --- /dev/null +++ b/include/boost/contract/ext_/preprocessor/traits/assertion/using.hpp @@ -0,0 +1,174 @@ + +#ifndef BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_HPP_ +#define BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_HPP_ + +#include +#include +#include +#include +#include +#include + +/* PRIVATE */ + +#define BOOST_CONTRACT_EXT_PP_USING_ASSERTION_NAME_PAREN_(name) \ + BOOST_PP_IIF(BOOST_CONTRACT_EXT_PP_HAS_PAREN(name), \ + name \ + , \ + (name) \ + ) + +// Precondition: decl = `(new-name) as ...`. +#define BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NEW_NAME_YES_( \ + decl, traits) \ + ( \ + BOOST_CONTRACT_EXT_PP_KEYWORD_AS_REMOVE_FRONT( \ + BOOST_PP_TUPLE_EAT(1) decl) \ + , \ + BOOST_CONTRACT_EXT_PP_TRAITS_PUSH_BACK(traits, \ + BOOST_CONTRACT_EXT_PP_PAREN_FRONT(decl) BOOST_PP_EMPTY) \ + ) + +#define BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NEW_NAME_NO_( \ + decl, traits) \ + (decl, BOOST_CONTRACT_EXT_PP_TRAITS_PUSH_BACK(traits, BOOST_PP_EMPTY)) + +// Precondition: decl = `(new-name) ...`. +// Implementation: NIL after decl in case EAT removes last tokens in decl. +#define BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NEW_NAME_MAYBE_( \ + decl, traits) \ + BOOST_PP_IIF(BOOST_CONTRACT_EXT_PP_KEYWORD_IS_AS_FRONT( \ + BOOST_PP_TUPLE_EAT(1) decl BOOST_PP_NIL), \ + BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NEW_NAME_YES_ \ + , \ + BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NEW_NAME_NO_ \ + )(decl, traits) + +// Precondition: decl = `using namespace ...`. +#define BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NAMESPACE_YES_( \ + decl, traits) \ + ( \ + BOOST_CONTRACT_EXT_PP_KEYWORD_NAMESPACE_REMOVE_FRONT( \ + BOOST_CONTRACT_EXT_PP_KEYWORD_USING_REMOVE_FRONT(decl)) \ + , \ + BOOST_CONTRACT_EXT_PP_TRAITS_PUSH_BACK(traits, \ + namespace BOOST_PP_EMPTY) \ + ) + +// Precondition: decl = `using ...`. +#define BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NAMESPACE_NO_( \ + decl, traits) \ + ( \ + BOOST_CONTRACT_EXT_PP_KEYWORD_USING_REMOVE_FRONT(decl) \ + , \ + BOOST_CONTRACT_EXT_PP_TRAITS_PUSH_BACK(traits, BOOST_PP_EMPTY) \ + ) + +// Precondition: decl = `template( ,,, ) ...`. +#define BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_TEMPLATE_PARAMS_YES_( \ + decl, traits) \ + ( \ + BOOST_PP_TUPLE_EAT(0) \ + BOOST_CONTRACT_EXT_PP_KEYWORD_TEMPLATE_REMOVE_FRONT(decl) \ + , \ + BOOST_CONTRACT_EXT_PP_TRAITS_PUSH_BACK( \ + traits, \ + BOOST_CONTRACT_EXT_PP_PAREN_FRONT( \ + BOOST_CONTRACT_EXT_PP_KEYWORD_TEMPLATE_REMOVE_FRONT(decl)) \ + BOOST_PP_EMPTY \ + ) \ + ) + +#define BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_TEMPLATE_PARAMS_NO_( \ + decl, traits) \ + (decl, BOOST_CONTRACT_EXT_PP_TRAITS_PUSH_BACK(traits, BOOST_PP_EMPTY)) + +/* PUBLIC */ + +// Precondition: decl = `wrapped-name`. +#define BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NAME_PARSE( \ + decl_traits) \ + ( \ + BOOST_PP_NIL \ + , \ + BOOST_CONTRACT_EXT_PP_TRAITS_PUSH_BACK( \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_SECOND(decl_traits), \ + BOOST_CONTRACT_EXT_PP_USING_ASSERTION_NAME_PAREN_( \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_FIRST(decl_traits)) \ + ) \ + ) + +#define BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NEW_NAME_PARSE( \ + decl_traits) \ + BOOST_PP_EXPAND( \ + BOOST_PP_IIF(BOOST_CONTRACT_EXT_PP_HAS_PAREN( \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_FIRST(decl_traits)), \ + BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NEW_NAME_MAYBE_ \ + , \ + BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NEW_NAME_NO_ \ + ) decl_traits \ + ) + +// Precondition: decl = `using ...`. +#define BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NAMESPACE_PARSE( \ + decl_traits) \ + BOOST_PP_EXPAND( \ + BOOST_PP_IIF( \ + BOOST_CONTRACT_EXT_PP_KEYWORD_IS_NAMESPACE_FRONT( \ + BOOST_CONTRACT_EXT_PP_KEYWORD_USING_REMOVE_FRONT( \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_FIRST( \ + decl_traits \ + ))) \ + , \ + BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NAMESPACE_YES_ \ + , \ + BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NAMESPACE_NO_ \ + ) decl_traits \ + ) + +// TODO: Do I really need all these PP_EXPAND here? + +#define BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_TEMPLATE_PARAMS_PARSE( \ + decl_traits) \ + BOOST_PP_EXPAND( \ + BOOST_PP_IIF(BOOST_CONTRACT_EXT_PP_KEYWORD_IS_TEMPLATE_FRONT( \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_FIRST(decl_traits)), \ + BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_TEMPLATE_PARAMS_YES_ \ + , \ + BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_TEMPLATE_PARAMS_NO_ \ + ) decl_traits \ + ) + +// decl = [template( c++-template-parameter, ... )] +// using [namespace | (new-name) as] wrapped-name +#define BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS(decl) \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_DONE( \ + BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NAME_PARSE( \ + BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NEW_NAME_PARSE( \ + BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NAMESPACE_PARSE( \ + BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_TEMPLATE_PARAMS_PARSE( \ + BOOST_CONTRACT_EXT_PP_ASSERTION_TRAITS_KIND_SET(using, \ + BOOST_CONTRACT_EXT_PP_DECL_TRAITS_INIT( \ + decl \ + ))))))) + +// Index 0 below already used and reserved for ASSERTION_TRAITS_KIND. + +// Expand to `(,,,) | EMPTY()`. +#define BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_TEMPLATE_PARAMS(traits) \ + BOOST_CONTRACT_EXT_PP_TRAITS_ELEM(1, traits)() + +// Expand to `namespace | EMPTY()`. +#define BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NAMESPACE(traits) \ + BOOST_CONTRACT_EXT_PP_TRAITS_ELEM(2, traits)() + +// Expand to `token | EMPTY()`. +#define BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NEW_NAME(traits) \ + BOOST_CONTRACT_EXT_PP_TRAITS_ELEM(3, traits)() + +// Expand to `(,,,)`. +#define BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS_NAME(traits) \ + BOOST_CONTRACT_EXT_PP_TRAITS_ELEM(4, traits) + +#endif // #include guard + diff --git a/include/boost/contract/ext_/preprocessor/traits/assertions.hpp b/include/boost/contract/ext_/preprocessor/traits/assertions.hpp new file mode 100644 index 0000000..79921ba --- /dev/null +++ b/include/boost/contract/ext_/preprocessor/traits/assertions.hpp @@ -0,0 +1,86 @@ + +#ifndef BOOST_CONTRACT_EXT_PP_ASSERTIONS_TRAITS_HPP_ +#define BOOST_CONTRACT_EXT_PP_ASSERTIONS_TRAITS_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +/* PRIVATE */ + +// TODO: To be correct, I should probably check that using is after +// template(,,,) here, and not just check IS_TEMPLATE_FRONT... + +#define BOOST_CONTRACT_EXT_PP_ASSERTIONS_TRAITS_APPEND_ASSERTION_( \ + s, decl, a, d, allow_oldof, allow_return, traits) \ + ( \ + a, \ + d, \ + allow_oldof, \ + allow_return, \ + BOOST_PP_LIST_APPEND_D( \ + d, \ + traits, \ + ( \ + BOOST_PP_IIF(BOOST_CONTRACT_EXT_PP_KEYWORD_IS_NAMESPACE_FRONT( \ + decl), \ + BOOST_CONTRACT_EXT_PP_NAMESPACE_ASSERTION_TRAITS \ + , BOOST_PP_IIF(BOOST_CONTRACT_EXT_PP_KEYWORD_IS_USING_FRONT( \ + decl), \ + BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS \ + , BOOST_PP_IIF(BOOST_CONTRACT_EXT_PP_KEYWORD_IS_TEMPLATE_FRONT(\ + decl), \ + BOOST_CONTRACT_EXT_PP_USING_ASSERTION_TRAITS \ + , BOOST_PP_IIF(BOOST_CONTRACT_EXT_PP_KEYWORD_IS_TYPEDEF_FRONT( \ + decl), \ + BOOST_CONTRACT_EXT_PP_TYPEDEF_ASSERTION_TRAITS \ + , \ + BOOST_CONTRACT_EXT_PP_BOOL_ASSERTION_TRAITS \ + ))))(decl), \ + BOOST_PP_NIL \ + ) \ + ) \ + ) + +#define BOOST_CONTRACT_EXT_PP_ASSERTIONS_TRAITS_ASSERTION_( \ + s, a_d_oldof_return_traits, decl) \ + BOOST_CONTRACT_EXT_PP_ASSERTIONS_TRAITS_APPEND_ASSERTION_( \ + s, \ + decl, \ + BOOST_PP_TUPLE_ELEM(5, 0, a_d_oldof_return_traits), \ + BOOST_PP_TUPLE_ELEM(5, 1, a_d_oldof_return_traits), \ + BOOST_PP_TUPLE_ELEM(5, 2, a_d_oldof_return_traits), \ + BOOST_PP_TUPLE_ELEM(5, 3, a_d_oldof_return_traits), \ + BOOST_PP_TUPLE_ELEM(5, 4, a_d_oldof_return_traits) \ + ) + +#define BOOST_CONTRACT_EXT_PP_ASSERTIONS_TRAITS_( \ + a, d, s, allow_oldof, allow_return, decl) \ + BOOST_PP_SEQ_FOLD_LEFT_ ## s( \ + BOOST_CONTRACT_EXT_PP_ASSERTIONS_TRAITS_ASSERTION_, \ + (a, d, allow_oldof, allow_return, BOOST_PP_NIL), \ + BOOST_CONTRACT_EXT_PP_TRAITS_AUX_ENUM_TO_SEQ decl \ + ) + +#define BOOST_CONTRACT_EXT_PP_ASSERTIONS_TRAITS_A_D_S_( \ + a, d, s, allow_oldof, allow_return, decl) \ + BOOST_PP_IIF(BOOST_CONTRACT_EXT_PP_IS_EMPTY decl, \ + BOOST_PP_NIL BOOST_PP_TUPLE_EAT(6) \ + , \ + BOOST_CONTRACT_EXT_PP_ASSERTIONS_TRAITS_ \ + )(a, d, s, allow_oldof, allow_return, decl) + +/* PUBLIC */ + +#define BOOST_CONTRACT_EXT_PP_ASSERTIONS_TRAITS_A_D_S(a, d, s, decl) \ + BOOST_CONTRACT_EXT_PP_ASSERTIONS_TRAITS_A_D_S_(a, d, s, 1, 1, decl) + +#define BOOST_CONTRACT_EXT_PP_ASSERTIONS_TRAITS(decl) \ + BOOST_CONTRACT_EXT_PP_ASSERTIONS_TRAITS_A_D_S(1, 1, 1, decl) + +#endif // #include guard + diff --git a/include/boost/contract/ext_/preprocessor/traits/aux_/enum_to_seq.hpp b/include/boost/contract/ext_/preprocessor/traits/aux_/enum_to_seq.hpp new file mode 100644 index 0000000..6cc2a48 --- /dev/null +++ b/include/boost/contract/ext_/preprocessor/traits/aux_/enum_to_seq.hpp @@ -0,0 +1,46 @@ + +#ifndef BOOST_CONTRACT_EXT_PP_TRAITS_AUX_ENUM_TO_SEQ_HPP_ +#define BOOST_CONTRACT_EXT_PP_TRAITS_AUX_ENUM_TO_SEQ_HPP_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// NOTE: This algorithm is not so generic because it requires that the +// enumerated elements can be checked using IS_NIL (that assumption is usually +// only true for declaration traits so this is programmed here in the traits). + +/* PRIVATE */ + +// Wrapped with parenthesis after removal of NIL so to make it a pp-seq elem. +#define BOOST_CONTRACT_EXT_PP_TRAITS_AUX_ENUM_TO_SEQ_REMOVE_NIL_(back) \ + (BOOST_CONTRACT_EXT_PP_NIL_REMOVE_BACK(back)) + +#define BOOST_CONTRACT_EXT_PP_TRAITS_AUX_ENUM_TO_SEQ_BACK_(seq, back) \ + BOOST_PP_SEQ_POP_BACK(seq) \ + BOOST_PP_IIF(BOOST_CONTRACT_EXT_PP_IS_NIL_FRONT(back), \ + BOOST_PP_TUPLE_EAT(1) \ + , \ + BOOST_CONTRACT_EXT_PP_TRAITS_AUX_ENUM_TO_SEQ_REMOVE_NIL_ \ + )(back) + +#define BOOST_CONTRACT_EXT_PP_TRAITS_AUX_ENUM_TO_SEQ_(seq) \ + BOOST_CONTRACT_EXT_PP_TRAITS_AUX_ENUM_TO_SEQ_BACK_(seq, \ + BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(seq)), seq)) + +/* PUBLIC */ + +// Expand `x, ..., y[,]` (note a trailing commas is optionally allowed similarly +// to C++ enum declarations) to `(x)...(y)`. +#define BOOST_CONTRACT_EXT_PP_TRAITS_AUX_ENUM_TO_SEQ(...) \ + BOOST_CONTRACT_EXT_PP_TRAITS_AUX_ENUM_TO_SEQ_( \ + BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__ BOOST_PP_NIL)) + +#endif // #include guard + diff --git a/include/boost/contract/ext_/preprocessor/traits/aux_/params.hpp b/include/boost/contract/ext_/preprocessor/traits/aux_/params.hpp index 715bb81..8c9b8d8 100644 --- a/include/boost/contract/ext_/preprocessor/traits/aux_/params.hpp +++ b/include/boost/contract/ext_/preprocessor/traits/aux_/params.hpp @@ -115,11 +115,12 @@ BOOST_CONTRACT_EXT_PP_TRAITS_AUX_PARAMS_ \ )(d, s, allow_void, decl, param_parse_macro, default_replace_macro) -// Handle `decl == ()` (i.e., empty parameters). +// Handle `decl == ( )` (i.e., empty parameters). // Precondition: decl is 1-tuple. #define BOOST_CONTRACT_EXT_PP_TRAITS_AUX_PARAMS_HANDLE_EMPTY_( \ d, s, allow_void, decl, param_parse_macro, default_replace_macro) \ - BOOST_PP_IIF(BOOST_PP_IS_EMPTY(BOOST_PP_TUPLE_REM_CTOR(decl)), \ + BOOST_PP_IIF(BOOST_CONTRACT_EXT_PP_IS_EMPTY( \ + BOOST_PP_TUPLE_REM_CTOR(1, decl)), \ BOOST_PP_NIL BOOST_PP_TUPLE_EAT(6) \ , BOOST_PP_IIF(allow_void, \ BOOST_CONTRACT_EXT_PP_TRAITS_AUX_PARAMS_HANDLE_VOID_ \ diff --git a/include/boost/contract/ext_/preprocessor/traits/func.hpp b/include/boost/contract/ext_/preprocessor/traits/func.hpp index b240867..441a725 100644 --- a/include/boost/contract/ext_/preprocessor/traits/func.hpp +++ b/include/boost/contract/ext_/preprocessor/traits/func.hpp @@ -2,6 +2,7 @@ #ifndef BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_HPP_ #define BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_HPP_ +#include #include #include #include @@ -27,6 +28,16 @@ // NOTE: These macros #definitions read TRITS_FUNC instead of FUNC_TRAITS to // avoid name clashes with macro #define in func/*. +#if defined(BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_AUX_INDEX_TEST) && \ + BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_AUX_INDEX_TEST < \ + BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_AUX_PRECONDITION_INDEX +# define BOOST_CONTRACT_EXT_PP_TRAITS_FUNC_PRECONDITION_PARSE_(decl_traits) \ + decl_traits +#else +# define BOOST_CONTRACT_EXT_PP_TRAITS_FUNC_PRECONDITION_PARSE_(decl_traits) \ + BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_PRECONDITION_PARSE(decl_traits) +#endif + #if defined(BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_AUX_INDEX_TEST) && \ BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_AUX_INDEX_TEST < \ BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_AUX_VIRT_INDEX @@ -176,6 +187,7 @@ // WARNING: Order of these macros must match ..._INDEX values (see index.hpp). #define BOOST_CONTRACT_EXT_PP_FUNC_TRAITS(decl) \ BOOST_CONTRACT_EXT_PP_TRAITS_FUNC_DONE_( \ + BOOST_CONTRACT_EXT_PP_TRAITS_FUNC_PRECONDITION_PARSE_( \ BOOST_CONTRACT_EXT_PP_TRAITS_FUNC_VIRT_PARSE_( \ BOOST_CONTRACT_EXT_PP_TRAITS_FUNC_TRAILING_RETURN_PARSE_( \ BOOST_CONTRACT_EXT_PP_TRAITS_FUNC_EXCEPT_PARSE_( \ @@ -191,7 +203,7 @@ BOOST_CONTRACT_EXT_PP_TRAITS_FUNC_ACCESS_PARSE_( \ BOOST_CONTRACT_EXT_PP_DECL_TRAITS_INIT( \ decl \ - ))))))))))))))) + )))))))))))))))) #endif // #include guard diff --git a/include/boost/contract/ext_/preprocessor/traits/func/aux_/index.hpp b/include/boost/contract/ext_/preprocessor/traits/func/aux_/index.hpp index 31be781..be4d9ed 100644 --- a/include/boost/contract/ext_/preprocessor/traits/func/aux_/index.hpp +++ b/include/boost/contract/ext_/preprocessor/traits/func/aux_/index.hpp @@ -44,7 +44,9 @@ #define BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_AUX_VIRT_INDEX \ BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_AUX_OVERRIDE_INDEX -#define BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_AUX_DONE_INDEX 22 +#define BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_AUX_PRECONDITION_INDEX 22 + +#define BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_AUX_DONE_INDEX 23 #endif // #include guard diff --git a/include/boost/contract/ext_/preprocessor/traits/func/precondition.hpp b/include/boost/contract/ext_/preprocessor/traits/func/precondition.hpp new file mode 100644 index 0000000..9699040 --- /dev/null +++ b/include/boost/contract/ext_/preprocessor/traits/func/precondition.hpp @@ -0,0 +1,47 @@ + +#ifndef BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_PRECONDITION_HPP_ +#define BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_PRECONDITION_HPP_ + +#include +#include + +/* PRIVATE */ + +// Precondition: decl = `(,,,) ...` from `precondition(,,,) ...` originally in +// decl. This macro will also parse `(,,,)` into a pp-list of assertion traits. +#define BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_PRECONDITION_(decl, traits) \ + ( \ + BOOST_PP_TUPLE_EAT(0) decl \ + , \ + BOOST_CONTRACT_EXT_PP_ASSERTIONS_TRAITS( \ + BOOST_CONTRACT_EXT_PP_PAREN_FRONT(decl)) \ + ) + +// Precondition: decl = `precondition(,,,) ...`. +#define BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_PRECONDITION_YES_(decl, traits) \ + BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_PRECONDITION_( \ + BOOST_CONTRACT_EXT_PP_KEYWORD_PRECONDITION_REMOVE_FRONT(decl), \ + traits \ + ) + +#define BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_PRECONDITION_NO_(decl, traits) \ + (decl, BOOST_CONTRACT_EXT_PP_TRAITS_PUSH_BACK(traits, BOOST_PP_NIL)) + +#define BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_PRECONDITION_PARSE_ARGS_( \ + decl, traits) \ + BOOST_PP_IIF(BOOST_CONTRACT_EXT_PP_KEYWORD_IS_PRECONDITION_FRONT(decl), \ + BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_PRECONDITION_YES_ \ + , \ + BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_PRECONDITION_NO_ \ + )(decl, traits) + +/* PUBLIC */ + +#define BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_PRECONDITION_PARSE(decl_traits) \ + BOOST_CONTRACT_EXT_PP_EXPAND_ONCE( \ + BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_PRECONDITION_PARSE_ARGS_ \ + decl_traits \ + ) + +#endif // #include guard + diff --git a/include/boost/contract/ext_/preprocessor/traits/func/template.hpp b/include/boost/contract/ext_/preprocessor/traits/func/template.hpp index 00e6438..72c1bd2 100644 --- a/include/boost/contract/ext_/preprocessor/traits/func/template.hpp +++ b/include/boost/contract/ext_/preprocessor/traits/func/template.hpp @@ -3,19 +3,20 @@ #define BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_TEMPLATE_HPP_ #include -#include #include #include +#include +#include #include #include /* PRIVATE */ -// params = `(,,,)` from `template(,,,) ...` originally in decl, and now this -// also parses params into a pp-list of actual template parameter traits. -#define BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_TEMPLATE_(decl_params, traits) \ +// Precondition: decl = `(,,,) ...` from `template(,,,) ...` originally in decl. +// This macro will also parse `(,,,)` into a pp-list of template param traits. +#define BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_TEMPLATE_(decl, traits) \ ( \ - BOOST_CONTRACT_EXT_PP_DECL_TRAITS_FIRST(decl_params) \ + BOOST_PP_TUPLE_EAT(0) decl \ , \ BOOST_CONTRACT_EXT_PP_TRAITS_PUSH_BACK( \ BOOST_CONTRACT_EXT_PP_TRAITS_PUSH_BACK( \ @@ -23,19 +24,14 @@ template BOOST_PP_EMPTY \ ), \ BOOST_CONTRACT_EXT_PP_TEMPLATE_PARAMS_TRAITS( \ - BOOST_CONTRACT_EXT_PP_DECL_TRAITS_SECOND(decl_params)) \ + BOOST_CONTRACT_EXT_PP_PAREN_FRONT(decl)) \ ) \ ) +// Precondition: decl = `template(,,,) ...`. #define BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_TEMPLATE_YES_(decl, traits) \ BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_TEMPLATE_( \ - BOOST_CONTRACT_EXT_PP_TRAITS_AUX_KEYWORD_PAREN( \ - decl, \ - BOOST_CONTRACT_EXT_PP_KEYWORD_IS_TEMPLATE_FRONT, \ - BOOST_CONTRACT_EXT_PP_KEYWORD_TEMPLATE_REMOVE_FRONT \ - ), \ - traits \ - ) + BOOST_CONTRACT_EXT_PP_KEYWORD_TEMPLATE_REMOVE_FRONT(decl), traits) #define BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_TEMPLATE_NO_(decl, traits) \ ( \ diff --git a/test/pp_func_traits/Jamfile.v2 b/test/pp_func_traits/Jamfile.v2 index 1b96f13..7a299bd 100644 --- a/test/pp_func_traits/Jamfile.v2 +++ b/test/pp_func_traits/Jamfile.v2 @@ -20,6 +20,7 @@ test-pp ref ; test-pp except ; test-pp trailing_return ; test-pp virt ; +test-pp precondition ; # TODO: Try to automatically run and test wave too... Maybe something like this: # SHELL "wave access.cpp" ; diff --git a/test/pp_func_traits/precondition.cpp b/test/pp_func_traits/precondition.cpp new file mode 100644 index 0000000..9b283b5 --- /dev/null +++ b/test/pp_func_traits/precondition.cpp @@ -0,0 +1,59 @@ + +#include +#if !BOOST_PP_VARIADICS +# error "this compiler does not support variadic macros" +#else + +#include +#define BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_AUX_INDEX_TEST \ + BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_AUX_PRECONDITION_INDEX + +#include "../aux_/pp_traits.hpp" +#include +#include + +#define BOOST_CONTRACT_TEST_(precondition_) \ + BOOST_CONTRACT_TEST_AUX_PP_TRAITS( \ + BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_PRECONDITION, \ + BOOST_CONTRACT_EXT_PP_FUNC_TRAITS, \ + (std::map&) (f) ( int x, (std::map&) y ) \ + throw(int, double) override final, \ + precondition_, \ + postcondition(x == 0 ? y.empty() : true), \ + precondition_ \ + ) + +int main ( ) { + BOOST_CONTRACT_TEST_( BOOST_PP_EMPTY() ) + + BOOST_CONTRACT_TEST_( precondition( ) ) + + BOOST_CONTRACT_TEST_( precondition( x >= 0, y, z ) ) + + BOOST_CONTRACT_TEST_( + precondition( + namespace (py) as boost::python, + + using namespace std, + using std::placeholders::_1, + using typename T::value_type, + using (std::map::insert), + using (typename M::key_type), + using (iv) as vector, + using (icmap) as (map), + template( typename T ) using (vt) as vector, + template( typename T, int U ) using (xtu) as (x), + + typedef unsigned long ul, + typedef (map) icmap, + + x >= 0, + y.size() == x, + ) + ) + + return BOOST_CONTRACT_TEST_AUX_PP_TRAITS_REPORT_ERRORS; +} + +#endif // variadics + diff --git a/test/pp_func_traits/virt.cpp b/test/pp_func_traits/virt.cpp index 7f25739..bfce2eb 100644 --- a/test/pp_func_traits/virt.cpp +++ b/test/pp_func_traits/virt.cpp @@ -12,8 +12,6 @@ #include #include -#include - #define BOOST_CONTRACT_TEST_VIRT_(func_traits) \ BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_FINAL(func_traits) \ BOOST_CONTRACT_EXT_PP_FUNC_TRAITS_OVERRIDE(func_traits)