C++ 带有函子的自动类型推断不起作用
可能重复:C++ 带有函子的自动类型推断不起作用,c++,c++11,bind,std,stdbind,C++,C++11,Bind,Std,Stdbind,可能重复: void foo0(int val){std::cout我猜std::bind周围的括号会让解析器认为您正在声明名为applyWithFoo0和applyFoo1的函数 bind返回一个functor,auto应该能够检测它的类型 试试这个: int main(int argc, char* argv[]) { auto applyWithFoo0 = std::bind(foo0, std::placeholders::_
void foo0(int val){std::cout我猜std::bind周围的括号会让解析器认为您正在声明名为applyWithFoo0和applyFoo1的函数
bind返回一个functor,auto应该能够检测它的类型
试试这个:
int main(int argc, char* argv[]) {
auto applyWithFoo0 = std::bind(foo0, std::placeholders::_1);
//std::function<void (int)> applyWithFoo0 std::bind(foo0, std::placeholders::_1) ); // use this instead to make compile
auto applyFoo1 = std::bind(foo1, std::placeholders::_1, applyWithFoo0);
foo2(123, applyFoo1);
}
intmain(intargc,char*argv[]){
autoapplyWithFoo0=std::bind(foo0,std::占位符::_1);
//std::函数applyWithFoo0 std::bind(foo0,std::占位符::_1));//改为使用此函数进行编译
autoapplyfoo1=std::bind(foo1,std::占位符::\u1,applyWithFoo0);
foo2(123,applyFoo1);
}
我猜std::bind周围的括号会让解析器认为您正在声明名为applyWithFoo0和applyFoo1的函数
bind返回一个functor,auto应该能够检测它的类型
试试这个:
int main(int argc, char* argv[]) {
auto applyWithFoo0 = std::bind(foo0, std::placeholders::_1);
//std::function<void (int)> applyWithFoo0 std::bind(foo0, std::placeholders::_1) ); // use this instead to make compile
auto applyFoo1 = std::bind(foo1, std::placeholders::_1, applyWithFoo0);
foo2(123, applyFoo1);
}
intmain(intargc,char*argv[]){
autoapplyWithFoo0=std::bind(foo0,std::占位符::_1);
//std::函数applyWithFoo0 std::bind(foo0,std::占位符::_1));//改为使用此函数进行编译
autoapplyfoo1=std::bind(foo1,std::占位符::\u1,applyWithFoo0);
foo2(123,applyFoo1);
}
问题在于std::bind
处理“绑定表达式”(就像您的applyWithFooo0
)与其他类型不同。它不使用applyWithFoo0
作为参数调用foo1,而是尝试调用applyWithFoo0
并将其返回值传递给foo1。但是applyWithFoo0
不会返回任何可转换为std::function
的内容。处理“绑定表达式”的意图这样做是为了使它们易于组合。在大多数情况下,您可能不希望将绑定表达式作为函数参数传递,而只希望将其结果传递。如果将绑定表达式显式包装到函数
对象中,则函数
对象将直接传递给foo1,因为它不是“绑定表达式”因此不是由std::bind
专门处理的
考虑以下示例:
#include <iostream>
#include <functional>
int twice(int x) { return x*2; }
int main()
{
using namespace std;
using namespace std::placeholders;
auto mul_by_2 = bind(twice,_1);
auto mul_by_4 = bind(twice,mul_by_2); // #2
auto mul_by_8 = bind(twice,mul_by_4); // #3
cout << mul_by_8(1) << endl;
}
其中,noeval
告诉bind不要对表达式求值,而是直接将其传递给函数。但也许另一种方法——明确告诉bind将函子的结果传递给函数——会是一种更好的设计:
auto mul_by_8 = bind( twice, eval(mul_by_4) );
但是我想,现在已经太晚了…问题是std::bind
处理“bind expression”(就像你的applyWithFoo0
)与其他类型不同。它不使用applyWithFoo0
作为参数调用foo1,而是尝试调用applyWithFoo0
并将其返回值传递给foo1。但是applyWithFoo0
不会返回任何可转换为std::function
的内容。处理“绑定表达式”的意图这样做是为了使它们易于组合。在大多数情况下,您可能不希望将绑定表达式作为函数参数传递,而只希望将其结果传递。如果将绑定表达式显式包装到函数
对象中,则函数
对象将直接传递给foo1,因为它不是“绑定表达式”因此不是由std::bind
专门处理的
考虑以下示例:
#include <iostream>
#include <functional>
int twice(int x) { return x*2; }
int main()
{
using namespace std;
using namespace std::placeholders;
auto mul_by_2 = bind(twice,_1);
auto mul_by_4 = bind(twice,mul_by_2); // #2
auto mul_by_8 = bind(twice,mul_by_4); // #3
cout << mul_by_8(1) << endl;
}
其中,noeval
告诉bind不要对表达式求值,而是直接将其传递给函数。但也许另一种方法——明确告诉bind将函子的结果传递给函数——会是一种更好的设计:
auto mul_by_8 = bind( twice, eval(mul_by_4) );
但是我想,现在已经太迟了…最令人烦恼的解析错误?没有帮助。最令人烦恼的解析错误?没有帮助。只使用&foo0而不是bind(foo0,_1)有什么错?它已经是一元可调用的object@MSalters:这看起来确实是个骗局。使用std::function
似乎可以实现一种神奇的转换,它可以实现OP想要的功能。否则,右边就没有天真地期望的语义了。@Jonathan:实际上是关于curry的。为了简单起见,我省略了更多的参数。是的,我同意uld也可以使用lambdas。@MSalters:Thanx作为参考。我认为你是对的。请随意将其标记为dublicate。@MSalters:I认为你是对的。我希望在回答此问题之前我已经跟随了你的链接。使用&foo0而不是bind(foo0,_1)有什么不对?它已经是一元可调用的object@MSalters:这看起来确实是个骗局。使用std::function
似乎可以实现一种神奇的转换,它可以实现OP想要的功能。否则,右边就没有天真地期望的语义了。@Jonathan:实际上是关于curry的。为了简单起见,我省略了更多的参数。是的,我同意uld也可以使用lambdas。@MSalters:Thanx作为参考。我认为你是对的。请随意将其标记为dublicate。@MSalters:I认为你是对的。我希望在回答这个问题之前我已经跟随了你的链接。Boost.Bind提供了与你的noeval(Bind-expr)
相当的protect(Bind-expr)
。需要eval(Bind-expr)
将使编写嵌套表达式变得更加困难,因为您确实希望将它们视为单个表达式,例如bind(&Y::f,bind(&getY,bind(&getX,_1))
@JonathanWakely:有趣!我不知道protect
。谢谢.Boost.bind提供了与您的noeval相当的protect(bind expr)
(bind-expr)
。需要eval(bind-expr)
会使编写嵌套表达式变得更加困难,因为您确实希望它们被视为单个表达式,例如bind(&Y::f,bind(&getY,bind(&getX,_1))
@JonathanWakely:有趣!我不知道protect
。谢谢。