本文介绍了在 C++0x 中专门针对 lambda 的模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我编写了一个 traits 类,它让我可以在 C++0x(用 gcc 4.5.0 测试)中提取有关函数或函数对象的参数和类型的信息.一般情况处理函数对象:I've written a traits class that lets me extract information about the arguments and type of a function or function object in C++0x (tested with gcc 4.5.0). The general case handles function objects:template <typename F>struct function_traits { template <typename R, typename... A> struct _internal { }; template <typename R, typename... A> struct _internal<R (F::*)(A...)> { // ... }; typedef typename _internal<decltype(&F::operator())>::<<nested types go here>>;};然后我专门研究了全局范围内的普通函数:Then I have a specialization for plain functions at global scope:template <typename R, typename... A>struct function_traits<R (*)(A...)> { // ...};这很好用,我可以将函数传递到模板或函数对象中,并且它可以正常工作:This works fine, I can pass a function into the template or a function object and it works properly:template <typename F>void foo(F f) { typename function_traits<F>::whatever ...;}int f(int x) { ... }foo(f);如果不是将函数或函数对象传递给 foo,我想传递一个 lambda 表达式怎么办?What if, instead of passing a function or function object into foo, I want to pass a lambda expression?foo([](int x) { ... });这里的问题是 function_traits 的特化都不适用.C++0x 草案说表达式的类型是唯一的、未命名的、非联合类类型".对在表达式上调用 typeid(...).name() 的结果进行分解给了我似乎是 gcc 对 lambda 的内部命名约定,main::{lambda(int)#1},不是在语法上代表 C++ 类型名的东西.The problem here is that neither specialization of function_traits<> applies. The C++0x draft says that the type of the expression is a "unique, unnamed, non-union class type". Demangling the result of calling typeid(...).name() on the expression gives me what appears to be gcc's internal naming convention for the lambda, main::{lambda(int)#1}, not something that syntactically represents a C++ typename.简而言之,我可以在此处放入模板吗:In short, is there anything I can put into the template here:template <typename R, typename... A>struct function_traits<????> { ... }这将允许这个 traits 类接受一个 lambda 表达式吗?that will allow this traits class to accept a lambda expression?推荐答案我认为可以专门化 lambda 的特征并对未命名函子的签名进行模式匹配.这是适用于 g++ 4.5 的代码.尽管它有效,但 lambda 上的模式匹配似乎与直觉相反.我有内联评论.I think it is possible to specialize traits for lambdas and do pattern matching on the signature of the unnamed functor. Here is the code that works on g++ 4.5. Although it works, the pattern matching on lambda appears to be working contrary to the intuition. I've comments inline.struct X{ float operator () (float i) { return i*2; } // If the following is enabled, program fails to compile // mostly because of ambiguity reasons. //double operator () (float i, double d) { return d*f; }};template <typename T>struct function_traits // matches when T=X or T=lambda// As expected, lambda creates a "unique, unnamed, non-union class type"// so it matches here{ // Here is what you are looking for. The type of the member operator() // of the lambda is taken and mapped again on function_traits. typedef typename function_traits<decltype(&T::operator())>::return_type return_type;};// matches for X::operator() but not of lambda::operator()template <typename R, typename C, typename... A>struct function_traits<R (C::*)(A...)>{ typedef R return_type;};// I initially thought the above defined member function specialization of// the trait will match lambdas::operator() because a lambda is a functor.// It does not, however. Instead, it matches the one below.// I wonder why? implementation defined?template <typename R, typename... A>struct function_traits<R (*)(A...)> // matches for lambda::operator(){ typedef R return_type;};template <typename F>typename function_traits<F>::return_typefoo(F f){ return f(10);}template <typename F>typename function_traits<F>::return_typebar(F f){ return f(5.0f, 100, 0.34);}int f(int x) { return x + x; }int main(void){ foo(f); foo(X()); bar([](float f, int l, double d){ return f+l+d; });} 这篇关于在 C++0x 中专门针对 lambda 的模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
05-27 15:54
查看更多