diff --git a/include/turtle/detail/mock_impl.hpp b/include/turtle/detail/mock_impl.hpp index 59fe4e0..cbf5976 100644 --- a/include/turtle/detail/mock_impl.hpp +++ b/include/turtle/detail/mock_impl.hpp @@ -12,11 +12,15 @@ #include "function.hpp" #include "functor.hpp" +#include "pp_foreach.hpp" #include "signature.hpp" #include "signature_traits.hpp" #include "type_name.hpp" +#include +#include #include #include +#include #include namespace mock { namespace detail { @@ -65,17 +69,29 @@ namespace mock { namespace detail { return MOCK_ANONYMOUS_HELPER(identifier)(MOCK_FORWARD_PARAMS(arity, signature)); \ } -#define MOCK_METHOD_EXT(name, arity, signature, identifier) \ - MOCK_METHOD_AUX(name, arity, signature, identifier, ) \ - MOCK_METHOD_AUX(name, arity, signature, identifier, const) \ - MOCK_METHOD_HELPER(signature, identifier) -#define MOCK_CONST_METHOD_EXT(name, arity, signature, identifier) \ - MOCK_METHOD_AUX(name, arity, signature, identifier, const) \ - MOCK_METHOD_HELPER(signature, identifier) -#define MOCK_NON_CONST_METHOD_EXT(name, arity, signature, identifier) \ - MOCK_METHOD_AUX(name, arity, signature, identifier, ) \ +/// MOCK_METHOD_ITER((name, arity, signature, identifier), qualifier) +#define MOCK_METHOD_ITER(M_n_S_t, qualifier) \ + MOCK_METHOD_AUX(BOOST_PP_TUPLE_ELEM(0, M_n_S_t), \ + BOOST_PP_TUPLE_ELEM(1, M_n_S_t), \ + BOOST_PP_TUPLE_ELEM(2, M_n_S_t), \ + BOOST_PP_TUPLE_ELEM(3, M_n_S_t), \ + qualifier) + +/// MOCK_METHOD_EXT_IMPL( name, arity, signature, identifier, qualifiers... ) +#define MOCK_METHOD_EXT_IMPL(name, arity, signature, identifier, ...) \ + static_assert(arity == mock::detail::function_arity_t::value, "Arity mismatch"); \ + MOCK_PP_FOR_EACH(MOCK_METHOD_ITER, (name, arity, signature, identifier), __VA_ARGS__) \ MOCK_METHOD_HELPER(signature, identifier) +/// MOCK_METHOD_EXT( name, arity, signature, identifier [ , qualifiers...] ) +/// If qualifiers is not given, defaults to (const, ), i.e. const and non-const +#define MOCK_METHOD_EXT(...) \ + MOCK_METHOD_EXT_IMPL \ + BOOST_PP_IF(BOOST_PP_LESS_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), 4), (__VA_ARGS__, const, ), (__VA_ARGS__)) + +#define MOCK_CONST_METHOD_EXT(M, n, S, t) MOCK_METHOD_EXT(M, n, S, t, const) +#define MOCK_NON_CONST_METHOD_EXT(M, n, S, t) MOCK_METHOD_EXT(M, n, S, t, ) + #define MOCK_FUNCTION_HELPER(signature, identifier, prefix) \ prefix mock::detail::function& identifier##_mock(mock::detail::context& context, \ boost::unit_test::const_string instance) \ diff --git a/include/turtle/detail/pp_foreach.hpp b/include/turtle/detail/pp_foreach.hpp new file mode 100644 index 0000000..e5579dc --- /dev/null +++ b/include/turtle/detail/pp_foreach.hpp @@ -0,0 +1,58 @@ +// http://turtle.sourceforge.net +// +// Copyright 2025 Alexander Grund +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef MOCK_PP_FOREACH_HPP_INCLUDED +#define MOCK_PP_FOREACH_HPP_INCLUDED + +#include +#include + +/// Expand to `macro(data, elem)` for each element passed, similar to BOOST_PP_*_FOR_EACH +/// It supports empty arguments, +/// without causing a C4003 "not enough arguments for function-like macro invocation" warning on MSVC +#if BOOST_PP_VARIADICS_MSVC +# define MOCK_PP_FOR_EACH(macro, data, ...) \ + BOOST_PP_CAT(BOOST_PP_OVERLOAD(MOCK_PP_INVOKE_, __VA_ARGS__)(macro, data, __VA_ARGS__), BOOST_PP_EMPTY()) +#else +# define MOCK_PP_FOR_EACH(macro, data, ...) BOOST_PP_OVERLOAD(MOCK_PP_INVOKE_, __VA_ARGS__)(macro, data, __VA_ARGS__) +#endif + +#define MOCK_PP_INVOKE_1(macro, data, x) macro(data, x) +#define MOCK_PP_INVOKE_2(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_1(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_3(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_2(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_4(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_3(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_5(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_4(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_6(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_5(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_7(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_6(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_8(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_7(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_9(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_8(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_10(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_9(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_11(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_10(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_12(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_11(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_13(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_12(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_14(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_13(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_15(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_14(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_16(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_15(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_17(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_16(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_18(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_17(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_19(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_18(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_20(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_19(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_21(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_20(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_22(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_21(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_23(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_22(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_24(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_23(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_25(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_24(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_26(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_25(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_27(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_26(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_28(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_27(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_29(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_28(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_30(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_29(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_31(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_30(macro, data, __VA_ARGS__) +#define MOCK_PP_INVOKE_32(macro, data, x, ...) macro(data, x) MOCK_PP_INVOKE_31(macro, data, __VA_ARGS__) + +#endif // MOCK_PP_FOREACH_HPP_INCLUDED