如何将:: std :: vector参数绑定到仿函数?

Omn*_*ous 4 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);
}
Run Code Online (Sandbox Code Playgroud)

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

这不是最后的用途,但它是我想去的地方的垫脚石.我真正在做的是生成包装器函数,它们在编译时从未来/ promise类型系统中的promises中解包它们的参数.这些包装函数本身就是承诺.

在我的最终用例中,我可以依赖于仿函数::std::function.但是,对于更多通用仿函数它应该如何工作的想法会很好,因为我认为这是一个广泛有趣的问题.

Ker*_* SB 5

好的,首先,可以完成检测仿函数的arity,但它有点牵扯,最好留给一个单独的问题.假设您将在调用中指定仿函数的arity.类似地,有一些方法可以获得可调用对象的返回类型,但这也超出了这个问题的范围.我们假设void现在返回类型.

所以我们想说,

call(F f, C v);
Run Code Online (Sandbox Code Playgroud)

应该说f(v[0], v[1], ..., v[n-1]),哪里f有arity 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);
}
Run Code Online (Sandbox Code Playgroud)

我们需要帮手:

#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]...);
    }
};
Run Code Online (Sandbox Code Playgroud)

例:

#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);
}
Run Code Online (Sandbox Code Playgroud)

注意:在更高级的版本中,我将使用更多的模板机制推断出可调用对象的arity,并且我还推导出返回类型.为了实现这一点,你需要几个自由函数和各种CV限定类成员函数的特化,所以这对于这个问题来说太大了.