c++ - 如何将参数的 a::std::vector 绑定(bind)到仿函数?

标签 c++ templates c++11

我正在努力让这个程序正确编译:

#include <vector>
#include <iostream>

int f(int a, int b)
{
   ::std::cout << "f(" << a << ", " << b << ") == " << (a + b) << '\n';
   return a + b;
}

template <typename R, typename V>
R bind_vec(R (*f)(), const V &vec, int idx=0)
{
   return f();
}

template <typename R, typename V, typename Arg1, typename... ArgT>
R bind_vec(R (*f)(Arg1, ArgT...), const V &vec, int idx=0)
{
   const Arg1 &arg = vec[idx];
   auto call = [arg, f](ArgT... args) -> R {
      return (*f)(arg, args...);
   };
   return bind_vec(call, vec, idx+1);
}

int foo()
{
   ::std::vector<int> x = {1, 2};
   return bind_vec(f, x);
}

理想情况下,我希望 bind_vec 将任意仿函数作为参数,而不仅仅是函数指针。这个想法是在编译时从 ::std::vector 中提取函数参数。

这不是它的最终用途,但它是通往我想去的地方的垫脚石。我真正在做的是生成包装函数,在编译时将它们的参数从 future / promise 类型系统中的 promise 中解开。这些包装函数本身就是 promise 。

在我的最终用例中,我可以指望仿函数是 ::std::function。但如果能知道它应该如何适用于更一般的仿函数,那将是一件好事,因为我认为这是一个广泛有趣的问题。

最佳答案

好的,首先,可以检测仿函数的元数,但这有点复杂,最好留给一个单独的问题。假设您将在调用中指定仿函数的元数。同样,有一些方法可以获得可调用对象的返回类型,但这也超出了这个问题的范围。我们现在假设返回类型是 void

所以我们想说,

call(F f, C v);

应该是 f(v[0], v[1], ..., v[n-1]),其中 f 有元数 n.


这是一种方法:

template <unsigned int N, typename Functor, typename Container>
void call(Functor const & f, Container const & c)
{
    call_helper<N == 0, Functor, Container, N>::engage(f, c);
}

我们需要 helper :

#include <functional>
#include <cassert>

template <bool Done, typename Functor, typename Container,
          unsigned int N, unsigned int ...I>
struct call_helper
{
    static void engage(Functor const & f, Container const & c)
    {
        call_helper<sizeof...(I) + 1 == N, Functor, Container,
                    N, I..., sizeof...(I)>::engage(f, c);
    }
};

template <typename Functor, typename Container,
          unsigned int N, unsigned int ...I>
struct call_helper<true, Functor, Container, N, I...>
{
    static void engage(Functor const & f, Container const & c)
    {
        assert(c.size() >= N);
        f(c[I]...);
    }
};

示例:

#include <vector>
#include <iostream>

void f(int a, int b) { std::cout << "You said: " << a << ", " << b << "\n"; }

struct Func
{
    void operator()(int a, int b) const
    { std::cout << "Functor: " << a << "::" << b << "\n"; }
};

int main()
{
    std::vector<int> v { 20, 30 };
    call<2>(f, v);
    call<2>(Func(), v);
}

注释:在更高级的版本中,我会使用更多模板机制来推断可调用对象的元数,我还会推断返回类型。不过,要实现这一点,您需要对自由函数和各种 CV 限定的类成员函数进行一些专门化,因此对于这个问题来说这会变得太大了。

关于c++ - 如何将参数的 a::std::vector 绑定(bind)到仿函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13594721/

相关文章:

C++ #include 错误

c++ - SFINAE 条件和构造函数参数类型

c++ - 根据模板方法中不同类型的不同代码路径

c++11 随机 double 使用 uniform_real_distribution

c++ - 使用 json c++ 的输出在字段中获取奇怪的字符

c++ - 用于导出和 C 和 C++ API 的单个头文件

c++ - vector 迭代器不可递增

c++ - 是否有可用的演示 C/C++ OpenCV 程序可以从网络摄像头进行简单的球跟踪?

c++ - 从基类指针集合中调用非虚拟成员函数?

c++ - 类模板的别名