【问题标题】:C++, match custom placeholders with function argumentsC++,将自定义占位符与函数参数匹配
【发布时间】:2015-08-14 01:07:46
【问题描述】:

我正在尝试编写将执行以下操作的代码:假设我们调用了自定义绑定函数

auto bind_obj = bind(some_func, _1, "test")  

在我们拥有之后

auto res = bind_obj(42) 

其中函数 some_func:

int some_func(int val, string test)

如何将占位符与实际函数调用中提供的参数匹配,即 bind_obj(...)?

换句话说,是否可以遍历 std::tuple (这里的参数和占位符)和可变参数包(函数参数)到:

  1. 推断函数some_func的返回类型;
  2. 制作正确的 std::tuple 以便在 some_func() 调用中进一步使用它?

我正在尝试不使用 boost 和 std::functional 来做到这一点。我认为,我的主要问题是我不明白如何在运行时使用参数构建元组(所有占位符都正确替换)并推断返回类型。

我在 STL "functional.h" 中看到了 _Mu 模板结构,但它看起来过于复杂且过载。

【问题讨论】:

  • <functional> 标准头文件是 C++ 的一部分。 “纯 C++”是什么意思?
  • 我想手动编写参数和占位符之间的匹配(很可能,使用模板,是的)以上绑定只是通常使用类绑定函数的示例
  • 对不起,我认错了,应该是 bind(some_func, _1, "test") 然后:bind_obj(42)
  • 至少,只有如何同时迭代可变参数包(这里只有函数参数)和 std::tuple (包含函数参数和占位符),才能以正确的顺序构建具有函数参数的新元组

标签: c++ c++11 variadic-templates template-argument-deduction tuple-packing


【解决方案1】:

由于调用的参数列表和捕获的参数列表的大小不同,因此您不会真正迭代它们。取而代之的是,你会得到一个函数,它会根据参数的捕获方式进行评估:

  • 如果绑定元素是一个值,则返回该值
  • 如果绑定元素是占位符,则返回给定索引处的参数
  • 如果绑定元素是绑定函数,则返回此函数的计算结果

假设您的绑定对象包含一个名为b 的绑定参数std::tuple<B...>,那么您可以构造一个调用参数的std::tuple<...>,如下所示:

template <typename... A, std::size_t... I>
... bound::call(std::tuple<A...>&& aux, index_list<I...>) {
    auto args = std::make_tuple(get_argument<I>(this->b, a));
    // ...
}
template <typename... A>
... bound::operator()(A&&... args) {
    return this->call(std::tie(std::forward<A>(args)..., make_index_list<sizeof...A>());
}

这段代码 sn-p 只是展示了如何让参数匹配起来。真正的工作发生在 get_argument&lt;I&gt;(b, a) 函数中,如果 b 中索引 I 处的元素恰好是占位符,则该函数只会返回由占位符值指示的 a 的元素。

该代码不包含有关如何创建索引列表、如何确定调用排序后的返回类型或如何处理右值参数的详细信息...

【讨论】:

  • 谢谢!顺便说一句,据我所知,在 C++ 14 之前,我们不能使用 auto for operator() 作为返回类型。您能否就如何确定函数的返回类型提供指导?
  • @PeterLeontev:你真的会按照以下方式调用你的函数:fun(std::make_tuple(get_argument&lt;I&gt;(this-&gt;b, a))。类型就是这个表达式的decltype(...)。对于函数调用运算符,您只需使用 call() 助手的 decltype(...)。如果它拒绝在尾随返回类型中使用this 来获取this-&gt;b,您可能需要使用declval&lt;T&gt;()(T 是this-&gt;b 的类型)。
  • 再次感谢您。我尝试使用这种方法,但为什么我们需要 sizeof...A>?如果 sizeof...B > sizeof...A 会怎样?
  • 你是对的:所需的索引实际上不是用于A...,而是用于B...!我不知道在您的绑定对象类型中是否可以轻松获得相应的大小,但掌握它应该是微不足道的。 A... 和 B... 的大小应该完全独立。
猜你喜欢
  • 2015-03-21
  • 1970-01-01
  • 2015-12-24
  • 1970-01-01
  • 2022-12-21
  • 2019-04-08
  • 1970-01-01
  • 2017-10-03
  • 2017-07-31
相关资源
最近更新 更多