Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何将参数的::std::vector绑定到函子?_C++_Templates_C++11 - Fatal编程技术网

C++ 如何将参数的::std::vector绑定到函子?

C++ 如何将参数的::std::vector绑定到函子?,c++,templates,c++11,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, typ

我正在努力使该程序正确编译:

#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);
}
#包括
#包括
int f(int a,int b)
{

::std::cout好的,首先,可以检测函子的arity,但这有点复杂,最好留给一个单独的问题。让我们假设您将在调用中指定函子的arity。类似地,也有方法获取可调用对象的返回类型,但这也超出了这个问题的范围。让我们假设目前返回类型为
void

所以我们想说,

call(F f, C v);
也就是说,
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);
}
模板
void调用(函子常量&f,容器常量&c)
{
呼叫助手::啮合(f,c);
}
我们需要助手:

#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]...);
    }
};
#包括
#包括
模板
结构调用辅助程序
{
静态无效接合(函子常数&f、容器常数&c)
{
呼叫助手::啮合(f,c);
}
};
模板
结构调用辅助程序
{
静态无效接合(函子常数&f、容器常数&c)
{
断言(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);
}
#包括
#包括

void f(inta,intb){std::cout我成功地实现了您想要的功能。如果一开始我没有推导正确的返回类型,最简单的解释是,我将在后面演示如何添加它:

#include <vector>
#include <type_traits>

namespace {
  int f(int a, int b) { return 0; }
}

template <typename ...Args>
constexpr unsigned nb_args(int (*)(Args...)) {
  return sizeof...(Args);
}

template <typename F, typename V, typename ...Args>
auto bind_vec(F f, const V&, Args&& ...args)
 -> typename std::enable_if<sizeof...(Args) == nb_args(F()),void>::type
{
  f(std::forward<Args>(args)...);
}

template <typename F, typename V, typename ...Args>
auto bind_vec(F f, const V& v, Args&& ...args)
 -> typename std::enable_if<sizeof...(Args) < nb_args(F()),void>::type
{
  bind_vec(f, v, std::forward<Args>(args)..., v.at(sizeof...(Args)));
}

int main() {
  bind_vec(&f, std::vector<int>(), 1);
  return 0;
}

对于(成员)函数指针来说,这样做很容易,但是对于可能重载了
操作符()
的函子来说,这会变得困难得多。如果我们假设您有办法知道一个函数需要多少参数(并假设容器实际有那么多元素),您可以使用将向量展开为参数列表,例如使用
std::next
begin()
迭代器:

#include <utility>
#include <iterator>

template<class F, class Args, unsigned... Is>
auto invoke(F&& f, Args& cont, seq<Is...>)
  -> decltype(std::forward<F>(f)(*std::next(cont.begin(), Is)...))
{
  return std::forward<F>(f)(*std::next(cont.begin(), Is)...);
}

template<unsigned ArgC, class F, class Args>
auto invoke(F&& f, Args& cont)
  -> decltype(invoke(std::forward<F>(f), cont, gen_seq<ArgC>{}))
{
  return invoke(std::forward<F>(f), cont, gen_seq<ArgC>{});
}
请注意,您甚至不需要使用
function\u-arity
使
invoke
从上面为
std::function
工作:

template<class R, class... Ts, class Args>
R invoke(std::function<R(Ts...)> const& f, Args& cont){
  return invoke_1(f, cont, gen_seq<sizeof...(Ts)>{})
}
模板
R调用(std::函数const&f、Args&cont){
返回invoke_1(f,cont,gen_seq{})
}

我们可以简化这一点吗:您想要一个小工具,通过使用容器的前n个元素调用任意容器中的n个参数的函数来调用该函数吗?@KerrekSB:是的。但它必须是一个在运行时填充了元素的容器。最好它可以调用任何实现的
操作符()
@Xeo:哦,我想它实际上并不涉及正常意义上的咖喱。:-)这对带有
操作符()
的函子对象也有效吗?@KerrekSB-对
nb_args()
会有适当的重载。@flex:祝你创建一个-
操作符()好运)
可以重载。有了函数指针,用户在将其传递给函数之前就必须消除歧义。@Flexo:在这种情况下,我真的很担心,我可以指望函子是
::std::function
@Omnifarious:这很容易,你为什么不在问题中这么说?这显然适用于函子。如果没有你提到的算术计算,现在还不清楚如何扩展函子的另一个。我最终使用的方法与此最接近。但是@Xeo的答案也很好。我会+1这个,除了我不认为我能理解它的工作原理之外。-@Omnifarious:Whe问题到底出在哪里?对于索引技巧,我链接了lounge wiki,使用它有很多答案。对于其他问题,只要提问,我会尽力解释(更好)@Xeo:我想我缺少的是理解索引技巧。我会仔细阅读你发布的链接。
gen_seq
的定义是什么?哦!我明白了。它生成索引。嗯……还有ArgC,那必须手工提供吗?@Omnifarious:正如我所说,我在这篇文章中假设你有办法获得实际的参数函数(对象)应使用调用。对于
std::function
,很容易获取。添加了代码。
#include <utility>

template<class T> using Alias = T; // for temporary arrays

template<class F, class It, unsigned N, unsigned... Is>
auto invoke_2(F&& f, It (&&args)[N], seq<Is...>)
  -> decltype(std::forward<F>(f)(*args[Is]...))
{
  return std::forward<F>(f)(*args[Is]...);
}

template<class F, class Args, unsigned... Is>
auto invoke_1(F&& f, Args& cont, seq<Is...> s)
  -> decltype(invoke_2(std::forward<F>(f), std::declval<decltype(cont.begin())[sizeof...(Is)]>(), s))
{
  auto it = cont.begin();
  return invoke_2(std::forward<F>(f), Alias<decltype(it)[]>{(void(Is), ++it)...}, s);
}

template<unsigned ArgC, class F, class Args>
auto invoke(F&& f, Args& cont)
  -> decltype(invoke_1(std::forward<F>(f), cont, gen_seq<ArgC>{}))
{
  return invoke_1(std::forward<F>(f), cont, gen_seq<ArgC>{});
}
template<class F> struct function_arity;

// if you have the 'Signature' of a 'std::function' handy
template<class R, class... Args>
struct function_arity<R(Args...)>
  : std::integral_constant<std::size_t, sizeof...(Args)>{};

// if you only have the 'std::function' available
template<class R, class... Args>
struct function_arity<std::function<R(Args...)>>
  : function_arity<R(Args...)>{};
template<class R, class... Ts, class Args>
R invoke(std::function<R(Ts...)> const& f, Args& cont){
  return invoke_1(f, cont, gen_seq<sizeof...(Ts)>{})
}