假设我们必须使用由一组函数组成的相同旧式界面的多个版本。版本之间的区别在于命名约定以及每个函数调用后需要处理的每个函数中常用的最后一个参数。像
这样的东西bool f1_v1(double a, int *common_arg);
// .....
bool fN_v1(double a, bool b, char c, int *common_arg);
基于简单模板的包装看起来像
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;
它看起来很难看,不是吗?我们仍然需要宏来避免函数名的双重替换。 对此有优雅的解决方案吗?
答案 0 :(得分:1)
目前,C ++ 11或C ++ 14,我认为你只能简化wrapper
类,避免内部wrap
结构,使用部分特化如下
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;
};
};
因此,您可以按如下方式定义和使用_f1
和_fN
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;
如果您想按如下方式定义_f1
和_fN
wrapper<f1_v1> _f1;
wrapper<fN_v1> _fN;
您需要符合C ++ 17的编译器和auto
类型的非类型模板参数。
我没有C ++ 17编译器,但我认为wrapper
应定义如下
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;
};
};