【问题标题】:getting the type of operator() from a bind versus a lambda function从绑定与 lambda 函数中获取 operator() 的类型
【发布时间】:2016-04-02 16:13:48
【问题描述】:

请看下面的代码。在捕获 lambda 表达式的情况下,它可以正常工作和编译。虽然在使用绑定可调用表达式时,我会得到一个重载表达式表达式错误

main.cpp:13:60: error: decltype cannot resolve address of overloaded function 
 using FuncType = decltype(&std::decay<T>::type::operator()); 

如何编写代码,以便获取绑定函数的 operator() 方法的类型?绑定类型是std::_Bind&lt;void (*(std::_Placeholder&lt;2&gt;, std::_Placeholder&lt;1&gt;))(int, int)&gt;,我也不完全理解;我知道 void (*) (int, int) 是一种类型,它是一个指向函数的指针,它接收 int、int 并返回 void。我想我不明白语法 void *(x,y) (int,int);基本上是 x,y 部分。我假设在所有模板内容之后有一个方法 void operator()(int, int) 将得到解决, bind_f(x,y) 将调用并且我试图捕获该类型。

#include <iostream>
#include <functional>
#include <type_traits>

void tester(int x, int y) {
   std::cout << " x = " << x << " y = " << y << std::endl;
}

template <typename T>
class TypeChecker;

template <typename T>
using FuncType = decltype(&std::decay<T>::type::operator());

int main()  {
   using namespace std::placeholders;
   auto bind_f = std::bind(tester, _2, _1);
   bind_f(1,2);                            

   int y = 5;                              

   auto lambda = [y]() {                   
      std::cout << " y = " << y << std::endl;
   };                                        

   typedef FuncType<decltype(lambda)> x1;            
   typedef FuncType<decltype(bind_f)> x2;            

   //TypeChecker<decltype(bind_f)> t2;       

}                                            

【问题讨论】:

  • 绑定表达式有一个模板化的调用运算符 accepts any number and kind of arguments。非多态 lambda 具有单个非模板调用运算符。
  • 请问,为什么要首先使用bind?或者这只是为了造就?我并不是说这个问题不好,不要误解,只是指出非常实用的答案是“不要使用绑定”,因为建议不要使用它来支持 lambdas(尤其是在 14 中具有通用 lambdas )。
  • 这是有道理的,是的,我正在创建一些涵盖所有情况的东西,但是总的来说,我想让它不能与 bind 一起使用,我只是想有人可能会要求它与 bind 一起使用。我想知道是否有办法使 FuncType 允许两种类型,如template &lt;typename T, typename... Ts&gt; using FuncType = decltype(T::operator()(std::declval&lt;Ts&gt;()...))(Ts...);

标签: c++ c++11 lambda bind


【解决方案1】:

正如评论者所说,bind 对象上的 operator() 是一个模板化(即重载)函数,如果不选择所需的版本,您不能简单地使用 bind

我们可以通过在FuncTypestatic_cast'ing 中添加另一个模板参数来选择合适的函数,然后在我们创建 typedef 时明确说明:

template <typename T, typename... U>
using FuncType = decltype(static_cast<void(T::*)(U...) const>(&std::decay<T>::type::operator()));

然后

auto bind_f = std::bind(tester, _2, _1);                         

int y = 5;                              

auto lambda = [y]() {                   
   std::cout << " y = " << y << std::endl;
};                                        
   
using x1 = FuncType<decltype(lambda)>;
using x2 =  FuncType<decltype(bind_f), int&&, int&&>;
   
x1 p = &decltype(lambda)::operator();
(lambda.*p)();
   
x2 q = &decltype(bind_f)::operator();
(bind_f.*q)(1,2);

Live Demo

输出:

y = 5

x = 2 y = 1

我同意Nir Friedman when he said 完全避免bind; lambda 让事情变得更简单。

【讨论】:

  • 我认为std::decay&lt;T&gt;::type 部分在模板类型别名中是不必要的,但我把它留在了那里。
  • 还没有尝试过,但假设我希望返回类型是可变的,在这种情况下,我只需将其添加为另一个模板参数。这意味着如果我的 operator() 没有返回 void
  • @bjackfly:是的,稍作修改:Demo。这不是最简洁的例子,但你明白了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-15
  • 2018-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-03
相关资源
最近更新 更多