将功能模板转换为模板化函子

时间:2019-08-07 12:28:08

标签: c++ c++11 functor

我想知道是否有可能从功能模板创建功能对象。以下Functor结构从一个函数创建一个函数对象:

#include <iostream>

template <typename F, F* f>
struct Functor {
  template <typename... Ar>
  auto operator()(Ar&&... rg) -> decltype(f(std::forward<Ar>(rg)...)) {
    return f(std::forward<Ar>(rg)...);
  }
};

int plus_one(int a) {
  return a + 1;
}

int main () {

  std::cout << Functor<decltype(plus_one), &plus_one>()(1) << "\n";

  return 0;
}

这将创建类似

的结构
struct PlusOne {
  int operator()(int a) {
    return a + 1;
  }
}

现在,我想使用功能模板而不是功能:

template <typename T>
T plus_one(T a) {
  return a + 1;
}

我希望将其变成类似

struct PlusOne {
  template <class T>
  T operator()(T a) {
    return a + 1;
  }
};

这可能吗?我问这个问题的原因之一是,我将C ++ 14中的read通用lambda表达式变成了类似于我追求的仿函数:

  

例如,以下包含lambda-expression的通用语句:

 auto L = [](const auto& x, auto& y){ return x + y; };
     

可能导致创建闭包类型,并且对象的行为类似于以下结构:

struct {
  template <typename T, typename U>
  auto operator()(const T& x, U& y) const { return x + y; }
} L;

因此,我天真地希望有一些设施可以使我所追求的成为可能。不过我仅限于C ++ 11。

1 个答案:

答案 0 :(得分:2)

否,这是不可能的。模板名称本身可以以非常有限的方式使用。您必须先将其包装在一个类中,然后再进行传递。在C ++ 14中,使用lambda包装对函数的调用似乎是最简单的方法。然后,您可以通过多种方式使用它:

auto wrapper = [](const auto& x){ return plus_one(x); }

std::cout << wrapper(42) << "\n";
std::cout << std::invoke(wrapper, 42) << "\n";
std::cout << std::bind(wrapper, 42)() << "\n";
// etc.

在C ++ 11中,我们有点搞砸了。我们必须自己编写包装器:

struct Wrapper {
    template <typename T>
    auto operator()(const T& x) const
    {
        return plus_one(x);
    }
};

然后

Wrapper wrapper;
// same usage