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.但是,对于更多通用仿函数它应该如何工作的想法会很好,因为我认为这是一个广泛有趣的问题.
好的,首先,可以完成检测仿函数的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限定类成员函数的特化,所以这对于这个问题来说太大了.