lambda函数可以模板化吗?
在C ++ 11中,有没有办法模拟一个lambda函数? 或者它本身是太具体的模板?
我明白,我可以定义一个经典的模板类/函子,但问题更像是:该语言是否允许模板lambda函数?
2014年更新:C ++ 14今年已经发布,现在提供了与本例中相同语法的多形态lambda。 一些主要的编译器已经实现了它。
在它站立(在C + + 11),可悲的没有。 在灵活性和力量方面,多形性lambda将是优秀的。
他们最终成为单形的原因是因为概念。 概念使这个代码情况困难:
template <Constraint T> void foo(T x) { auto bar = [](auto x){}; // imaginary syntax }
在受限制的模板中,您只能调用其他受约束的模板。 (否则,约束无法检查。)可以foo
调用bar(x)
? lambda有什么限制(毕竟它的参数只是一个模板)?
概念还没有准备好处理这种事情; 它会需要更多的东西像late_check
(其中的概念没有被检查,直到被调用)和东西。 更简单的是放弃所有,坚持单形lambda。
然而,随着从C ++ 0x中移除概念,多态lambdaexpression式再次成为一个简单的命题。 不过,我找不到任何build议。 🙁
C ++ 11 lambda不能像其他答案中所述的模板化,但decltype()
似乎有助于在模板化类或函数中使用lambda。
#include <iostream> #include <string> using namespace std; template<typename T> void boring_template_fn(T t){ auto identity = [](decltype(t) t){ return t;}; std::cout << identity(t) << std::endl; } int main(int argc, char *argv[]) { std::string s("My string"); boring_template_fn(s); boring_template_fn(1024); boring_template_fn(true); }
打印:
My string 1024 1
我发现这个技术在使用模板代码的时候是有帮助的,但是意识到它仍然意味着lambda本身不能被模板化。
在C ++ 11中,lambda函数不能被模板化,但在ISO C ++标准的下一个版本(通常称为C ++ 14)中,将引入这个特性。 [资源]
用法示例:
auto get_container_size = [] (auto container) { return container.size(); };
请注意,虽然语法使用关键字auto
,但types推导不会使用auto
types推导的规则,而是使用模板参数推导的规则。 另请参阅通用lambdaexpression式的提议 (以及对此的更新 )。
我知道这个问题是关于C ++ 11的。 然而,对于那些在这个页面上search和登陆的人来说,现在在C ++ 14中支持模板化的lambda,并且名为Generic Lambdas。
大多数stream行的编译器现在都支持这个function。 Microsoft Visual Studio 2015支持。 铿锵支持。 GCC支持。
我想知道这是什么:
template <class something> inline std::function<void()> templateLamda() { return [](){ std::cout << something.memberfunc() }; }
我用类似的代码来生成一个模板,并想知道编译器是否会优化“包装”function。
看看Boost.Phoenix的多态lambdaexpression式: http : //www.boost.org/doc/libs/1_44_0/libs/spirit/phoenix/doc/html/index.html不需要C ++ 0x,由办法 :)
我不知道为什么没有人提出这个build议,但你可以写一个模板函数返回lambda函数。 以下解决了我的问题,我来到这个页面的原因:
template <typename DATUM> std::function<double(DATUM)> makeUnweighted() { return [](DATUM datum){return 1.0;}; }
现在,无论何时我需要一个接受给定types参数的函数(例如std::string
),我只是说
auto f = makeUnweighted<std::string>()
现在f("any string")
返回1.0
。
这就是我所说的“模板化lambda函数”的一个例子。 (这个特殊的例子是用来自动提供一个惰性加权函数,当有人不想加权他们的数据时,无论他们的数据是什么)。
有一个允许lambda模板的gcc扩展 :
// create the widgets and set the label base::for_each(_widgets, [] <typename Key_T, typename Widget_T> (boost::fusion::pair<Key_T, Widget_T*>& pair) -> void { pair.second = new Widget_T(); pair.second->set_label_str(Key_T::label); } );
_widgets
是一个std::tuple< fusion::pair<Key_T, Widget_T>... >
这是一个解决scheme,涉及将lamba包装在一个结构中:
template <typename T> struct LamT { static void Go() { auto lam = []() { T var; std::cout << "lam, type = " << typeid(var).name() << std::endl; }; lam(); } };
使用做:
LamT<int>::Go(); LamT<char>::Go(); #This prints lam, type = i lam, type = c
这个主要问题(除了额外的input)你不能在另一个方法中embedded这个结构定义,或者你得到(gcc 4.9)
error: a template declaration cannot appear at block scope
我也试过这样做:
template <typename T> using LamdaT = decltype( [](void) { std::cout << "LambT type = " << typeid(T).name() << std::endl; });
希望我能像这样使用它:
LamdaT<int>(); LamdaT<char>();
但是我得到的编译器错误:
error: lambda-expression in unevaluated context
所以这是行不通的,但即使编译也是有限的,因为我们仍然要把“使用LamdaT”放在文件范围(因为它是一个模板) lambdaexpression式。