2015-12-28 40 views
3

请看下面的代码。在捕获lambda表达式的情况下,它将工作并编译得很好。使用绑定调用表达我会得到一个超载表达表达错误从绑定与lambda函数获取运算符()的类型

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

我如何代码绑定功能,这使得我得到了运营商的类型()方法时,虽然?绑定类型是std::_Bind<void (*(std::_Placeholder<2>, std::_Placeholder<1>))(int, int)>,我也没有完全理解;我知道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;  

}            
+3

一个bind表达式有一个模板化的调用操作符[接受任意数量和种类的参数](https://ideone.com/K2nzuT)。一个非多态的lambda拥有一个非模板调用操作符。 –

+1

我可以问一下,你为什么想要首先使用绑定?或者这仅仅是为了教化?我并不是说这个问题不好,不要误解,只是指出实际的答案是“不要使用绑定”,因为它的使用被推荐为不支持lambda(特别是在14中有lambda类型) )。 –

+0

这是有道理的,是的,我创造的东西涵盖了所有的情况,但一般情况下,我想使它不能用于绑定我只是觉得有人可能会要求它与绑定一起工作。我想知道是否有一种方法可以使FuncType这样,它将允许使用FuncType = decltype(T :: operator()(std :: declval )这样的'template ()...))(TS ...); ' – bjackfly

回答

0

就像评论者说,你bind对象的operator()是,你不能简单地bind在没有选择的版本你想有一个模板(即超载)功能。

当我们使我们的typedef,我们可以通过添加另一个模板参数FuncTypestatic_cast“荷兰国际集团,以选择相应的功能,然后是明确解决这一问题:

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使事情变得更容易。

+0

我不认为'std :: decay :: type'部分在模板类型别名中是必需的,但我将它留在那里。 – AndyG

+0

还没有尝试过,但假设如果我想要返回类型是变量,我只是将其作为另一个模板参数在这种情况下添加。意思是如果我的operator()没有返回void – bjackfly

+0

@bjackfly:是的,稍作修改:[Demo](http://coliru.stacked-crooked.com/a/05bfeb038eb60fe7)。这不是最干净的例子,但你明白了。 – AndyG

相关问题