Reputation: 35
Let's assume we have to use several versions of the same old-style interface which consists of a set of functions. The difference between versions is in the naming convention and additional commonly used last argument in each function that we need to process after each function invocation. Something like
bool f1_v1(double a, int *common_arg);
// .....
bool fN_v1(double a, bool b, char c, int *common_arg);
Simple template based wrap looks like
template <typename T> struct wrapper;
template<typename _Res, typename... _ArgTypes>
struct wrapper<_Res(_ArgTypes...)> {
template <_Res (*f)(_ArgTypes...)>
struct wrap {
template <typename... Args>
_Res operator()(Args... args) {
int common_arg;
_Res res = f(args..., &common_arg);
// common processing....
// .....
return res;
};
};
};
wrapper<decltype(f1_v1)>::wrap<f1_v1> _f1;
// .....
wrapper<decltype(fN_v1)>::wrap<fN_v1> _fN;
It looks ugly, isn't it? And we still need macro to avoid double substitution of the function name. Is there an elegant solution for this?
Upvotes: 1
Views: 301
Reputation: 66200
At the moment, C++11 or C++14, I think you can only semplify the wrapper
class, avoiding the inner wrap
struct, using partial specialization as follows
template <typename T, T>
struct wrapper;
template <typename _Res, typename... _ArgTypes, _Res (*f)(_ArgTypes...)>
struct wrapper<_Res(_ArgTypes...), f>
{
template <typename... Args>
_Res operator()(Args... args)
{
int common_arg;
_Res res = f(args..., &common_arg);
// common processing....
return res;
};
};
So you can define and use _f1
and _fN
as follows
wrapper<decltype(f1_v1), f1_v1> _f1;
wrapper<decltype(fN_v1), fN_v1> _fN;
std::cout << _f1(0.1) << std::endl;
std::cout << _fN(0.1, true, 'c') << std::endl;
If you want define _f1
and _fN
as follows
wrapper<f1_v1> _f1;
wrapper<fN_v1> _fN;
you need a C++17 compliant compiler and the auto
type for non-type template argument.
I don't have a C++17 compiler but I suppose that wrapper
should be defined as follows
template <auto f>
struct wrapper
{
template <typename... Args>
_Res operator()(Args... args)
{
int common_arg;
_Res res = f(args..., &common_arg);
// common processing....
return res;
};
};
Upvotes: 1