Change MOCK_METHOD_EXT to add support for arbitrary amounts of method modifiers

This commit is contained in:
Alexander Grund 2025-04-20 12:41:45 +02:00
parent 8151fe20c7
commit 09bb6b5371
2 changed files with 83 additions and 9 deletions

View file

@ -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 <boost/preprocessor/comparison/less_equal.hpp>
#include <boost/preprocessor/if.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <type_traits>
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<signature>::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<signature>& identifier##_mock(mock::detail::context& context, \
boost::unit_test::const_string instance) \

View file

@ -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 <boost/preprocessor/expand.hpp>
#include <boost/preprocessor/facilities/overload.hpp>
/// 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