是否可以转换嵌套的C ++ 11绑定表达式?例如,在下面的代码中,与f
关联的绑定表达式将首先将其参数乘以2,然后在结果中添加一个:
#include <iostream>
#include <functional>
using namespace std::placeholders;
int main(int argc, char *argv[])
{
auto add1 = [](int x) { return x+1; };
auto mul2 = [](int x) { return x*2; };
auto f = std::bind(add1, std::bind(mul2, _1));
std::cout << f(0) << '\n';
return 0;
}
我们是否可以创建f
的转换版本,而首先添加一个,然后将结果乘以2;结果的行为就像定义为:
auto f2 = std::bind(mul2, std::bind(add1, _1));
这个例子简化为它的结构类似于列表;而绑定表达式通常更像是树。
答案 0 :(得分:5)
std::bind
是一个黑盒子。它不支持内省(除了std::result_of
和std::is_bind_expression
)或多态(除std::placeholders
之外)。当您致电f(0)
时,它会编译为0*2+1
的原生代码。
在黑盒子里面就像一个表达式模板,引用组合的仿函数类型并为任何绑定参数提供存储。这种实现与编译器有关,平台细节实际上差别很大。
如果要移植操作表达式,请查看Boost.Proto通用表达式模板库。不过,这很重要。
答案 1 :(得分:3)
这是对VS2013的残酷破解,并且完全不可移植,但我有兴趣看看我能不能做些什么。它可能无法解决您的问题,但我认为值得分享。由于std::bind
的返回值是实现定义的,因此可移植性将成为此问题的一大障碍。大部分模板演绎也有很多手段。
template<class A, class B, class C>
std::_Bind<false, void, B&, std::_Bind<false, void, A&, C>>
inverse(std::_Bind<false, void, A&, std::_Bind<false, void, B&, C>> f) {
A func_a;
B func_b;
return std::bind(func_b, std::bind(func_a, _1));
}
int main() {
auto add1 = [](int x) { return x+1; };
auto mul2 = [](int x) { return x*2; };
auto f = std::bind(add1, std::bind(mul2, _1));
std::cout << f(0) << '\n';
auto g = inverse(f);
std::cout << g(0) << '\n';
return 0;
}