带有函子的自动类型推理不起作用
Auto type inference with functor does not work
可能重复:
std::绑定绑定函数
void foo0(int val) { std::cout << "val " << val << "n"; }
void foo1(int val, std::function<void (int)> ftor) { ftor(val); }
void foo2(int val, std::function<void (int)> ftor) { ftor(val); }
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);
}
上面的示例没有编译,会出现多个错误,如:Error 1 error C2780: '_Ret std::tr1::_Callable_fun<_Ty,_Indirect>::_ApplyX(_Arg0 &&,_Arg1 &&,_Arg2 &&,_Arg3 &&,_Arg4 &&,_Arg5 &&,_Arg6 &&,_Arg7 &&,_Arg8 &&,_Arg9 &&) const' : expects 10 arguments - 2 provided
使用具有显式类型的注释行进行编译。似乎auto
推断的类型是不正确的。在这种情况下,auto
有什么问题
平台:MSVC 10 SP 1,GCC 4.6.1
问题是std::bind
对待"绑定表达式"(如applyWithFoo0
)与其他类型不同。它不使用applyWithFoo0
作为参数来调用foo1,而是尝试调用applyWithFoo0
并将其返回值传递给foo1。但是applyWithFoo0
不返回任何可转换为std::function<void(int)>
的内容。这样处理"绑定表达式"的目的是使它们易于组合。在大多数情况下,您可能不希望绑定表达式作为函数参数传递,而只希望传递它们的结果。如果将绑定表达式显式包装到function<>
对象中,则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;
}
这实际上是编译和工作的,因为bind并没有像从绑定表达式#2和#3中预期的那样将函子传递两次,而是实际计算传递的绑定表达式,并且将其结果用作函数参数两次。在这里,它是故意的。但在您的案例中,您意外地被这种行为绊倒了,因为您实际上希望bind将函子本身传递给函数,而不是其求值值。将函子封装为函数<>对象显然是一个变通办法。
在我看来,这个设计决定有点尴尬,因为它引入了一种不规则性,人们必须知道才能正确使用绑定。也许,我们将来会有另一个更令人满意的工作,比如
auto applyFoo1 = bind( foo1, _1, noeval(applyWithFoo0) );
其中noeval
告诉bind不要计算表达式,而是直接将其传递给函数。但也许另一种方法——明确地告诉bind将函子的结果传递给函数——会是更好的设计:
auto mul_by_8 = bind( twice, eval(mul_by_4) );
但我想,现在已经太晚了。。。
我的猜测是,std::bind周围的括号会让解析器认为您在声明名为applyWithFoo0和applyFoo1的函数。
std::bind返回一个函数,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);
}
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 如何从C++中的依赖类型中获得它所依赖的类型
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如何获取std::result_of函数的返回类型
- 从父命名空间重载类型
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 推理类型如何工作"auto"和按引用调用?
- CAN模板类型推理考虑原始操作类型转换
- 从函数指针对标准 C++98 中的函数类型参数进行静态推理
- 在C++11类型推理过程中,控制优先级的规则是什么
- C++11 类型推理如何在浮点数或双精度数之间做出决定
- 带有函子的自动类型推理不起作用
- C++11 使用 lambda 和 std::function 进行类型推理
- 矩阵积的 Cholesky 的特征和 C++11 类型推理失败
- 使用模板化复合类型推理实现unique_copy
- 不知道C++11类型推理