I am using a C++preprocessor to batch generate function definitions, but there is an issue when passing parameters
#include <iostream>
#define FOR_EACH_FUNC(_) \
_(int, add, int a, int b) \
_(int, subtract, int a, int b)
#define FORWARD_FUNC(ret, func, ...) \
ret func(__VA_ARGS__) { \
impl->func(__VA_ARGS__); \ // error!
} \
FOR_EACH_FUNC(FORWARD_FUNC)
int main()
{
int r1 = add(1, 2);
int r2 = subtract(1, 2);
return 0;
}
The result I want is
int add(int a, int b) {
impl->add(a, b);
}
But the current result is
int add(int a, int b) {
impl->add(int a, int b);
}
Is there any way to solve this problem? Thanks
I tried using C++'s variable parameter template to solve it, but it was not successful
Supplementary explanation:
We have a library A that needs to be used by a third party, but it relies on many other libraries. In order to clean up the compilation dependencies of others, we have implemented an intermediate library B that calls the methods of A through dlopen/dlsys
(library A and its dependencies will be built into our system).
The problem here is: to implement a function, we need to first implement it in A, then define it in B as well, then define the function pointer, find the corresponding function address, and implement a simple logic to forward the request to A. I want to simplify this process
If all your arguments are trivially copyable (which stuff crossing a DLL boundary should be), you can use this:
#define FOR_EACH_FUNC(_) \
_(int, add, int(a), int(b)) \
_(int, subtract, int(a), int(b))
Which will just be a bracketed name in the function declaration but be a functional cast as an expression.
This won't work with multi-word type names like unsigned long long
, but you can use a typedef (using ull = unsigned long long;
) or std::type_identity_t<unsigned long long>
.
If you don't mind automatically named parameters (int _0, int _1
), you can do this with Boost.Preprocessor:
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/comma_if.hpp>
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/variadic/size.hpp>
#include <boost/preprocessor/variadic/to_seq.hpp>
#define NUMBERED_ARGUMENTS_DECL_IMPL(R, PREFIX, I, TYPE) BOOST_PP_COMMA_IF(I) TYPE BOOST_PP_CAT(PREFIX, I)
#define NUMBERED_ARGUMENTS_DECL(...) BOOST_PP_SEQ_FOR_EACH_I(NUMBERED_ARGUMENTS_DECL_IMPL, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
// `NUMBERED_ARGUMENTS_DECL(int, char, void*)` -> `int _0, char _1, void* _2`
#define NUMBERED_ARGUMENTS_EXPR_IMPL(Z, I, PREFIX) BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(PREFIX, I)
#define NUMBERED_ARGUMENTS_EXPR(...) BOOST_PP_REPEAT(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), NUMBERED_ARGUMENTS_EXPR_IMPL, _)
// `NUMBERED_ARGUMENTS_DECL(int, char, void*)` -> `_0, _1, _2`
#define FOR_EACH_FUNC(_) \
_(int, add, int, int) \
_(int, subtract, int, int)
#define FORWARD_FUNC(ret, func, ...) \
ret func(NUMBERED_ARGUMENTS_DECL(__VA_ARGS__)) { \
return impl->func(NUMBERED_ARGUMENTS_EXPR(__VA_ARGS__)); \
} \
FOR_EACH_FUNC(FORWARD_FUNC)