基于类模板的包装函数

时间:2017-04-15 01:36:39

标签: c++ c++11 templates variadic-templates

假设我们必须使用由一组函数组成的相同旧式界面的多个版本。版本之间的区别在于命名约定以及每个函数调用后需要处理的每个函数中常用的最后一个参数。像

这样的东西
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;

它看起来很难看,不是吗?我们仍然需要宏来避免函数名的双重替换。 对此有优雅的解决方案吗?

1 个答案:

答案 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;
       };
 };