tin*_*lyx 17 c++ lambda functional-programming c++11
我正在玩c ++ 11的功能.我发现奇怪的一件事是lambda函数的类型实际上不是函数<>类型.更重要的是,lambda似乎不能很好地使用类型推理机制.
附件是一个小例子,我在其中测试了翻转函数的两个参数以添加两个整数.(我使用的编译器是MinGW下的gcc 4.6.2.)在示例中,类型for addInt_f已使用函数<>显式定义,而addInt_l类型为类型推理的lambda auto.
当我编译的代码,该flip功能可以接受明确类型定义addInt的版本,但不是拉姆达版本,给了一个错误说,
testCppBind.cpp:15:27: error: no matching function for call to 'flip(<lambda(int, int)>&)'
接下来的几行显示lambda版本(以及'raw'版本)如果显式转换为适当的函数<>类型,则可以接受.
所以我的问题是:
为什么lambda函数首先没有function<>类型?在小例子中,为什么不addInt_l具有function<int (int,int)>类型而不是具有不同的lambda类型?从函数式编程的角度来看,函数/函数对象和lambda之间有什么区别?
如果存在这两者必须不同的根本原因.我听说lambda可以转换为function<>但它们是不同的.这是C++ 11,一个执行问题是设计问题/缺陷还是有区分两者,因为它是方式的好处?似乎addInt_l单独的类型签名提供了关于函数的参数和返回类型的足够信息.
有没有办法编写lambda,以便可以避免上面提到的显式类型转换?
提前致谢.
//-- testCppBind.cpp --
#include <functional>
using namespace std;
using namespace std::placeholders;
template <typename T1,typename T2, typename T3>
function<T3 (T2, T1)> flip(function<T3 (T1, T2)> f) { return bind(f,_2,_1);}
function<int (int,int)> addInt_f = [](int a,int b) -> int { return a + b;};
auto addInt_l = [](int a,int b) -> int { return a + b;};
int addInt0(int a, int b) { return a+b;}
int main() {
auto ff = flip(addInt_f); //ok
auto ff1 = flip(addInt_l); //not ok
auto ff2 = flip((function<int (int,int)>)addInt_l); //ok
auto ff3 = flip((function<int (int,int)>)addInt0); //ok
return 0;
}
Run Code Online (Sandbox Code Playgroud)
R. *_*des 41
std::function是一种用于存储任何类型的可调用对象的工具,无论其类型如何.为了做到这一点,它需要采用一些类型的擦除技术,这涉及一些开销.
任何可调用的都可以隐式转换为a std::function,这就是它通常无缝工作的原因.
我将重复以确保它变得清晰:std::function不仅仅是lambdas或函数指针的东西:它适用于任何类型的可调用.这包括struct some_callable { void operator()() {} };例如.这是一个简单的,但它可能是这样的:
struct some_polymorphic_callable {
template <typename T>
void operator()(T);
};
Run Code Online (Sandbox Code Playgroud)
lambda只是另一个可调用对象,类似于some_callable上面对象的实例.它可以存储在a中,std::function因为它是可调用的,但它没有类型擦除开销std::function.
委员会计划在未来制作lambdas多态,即看起来像some_polymorphic_callable上面的lambdas .std::function这样的lambda会是哪种类型?
现在...模板参数推导或隐式转换.选一个.这是C++模板的规则.
要将lambda作为std::function参数传递,需要隐式转换它.采用std::function参数意味着您选择隐式转换而不是类型推导.但是您的功能模板需要明确推断或提供签名.
解决方案?不要限制你的来电者std::function.接受任何类型的可赎回.
template <typename Fun>
auto flip(Fun&& f) -> decltype(std::bind(std::forward<Fun>(f),_2,_1))
{ return std::bind(std::forward<Fun>(f),_2,_1); }
Run Code Online (Sandbox Code Playgroud)
你现在可能在想我们为什么需要std::function呢.std::function为具有已知签名的可调用字符提供类型擦除.这基本上使得存储类型擦除的callables和编写virtual接口很有用.
function<>采用类型擦除.这允许将几种不同的类函数类型存储在a中function<>,但会导致较小的运行时间损失.类型擦除隐藏虚拟功能接口后面的实际类型(您的特定lambda).auto或传递作为模板参数)时没有任何开销,但您仍然可以灵活地与非模板代码进行交互function<>.另请注意,function<>它不是语言构造,而是可以使用简单语言功能实现的标准库的组件.function<>(库构造)的细节.当然,这使得实际写下返回类型变得更加困难,因为它不会直接为您提供参数类型.但是,使用一些元编程和一个Boost.FunctionTypes你可以从你传入的函数中推导出这些.在某些情况下,这是不可能的,例如使用模板化的函子operator().| 归档时间: |
|
| 查看次数: |
4683 次 |
| 最近记录: |