Cha*_*l72 60 c++ lambda templates c++11
可以lambda表达式被用来作为类模板参数?(注意这是比一个非常不同的问题这一个,其中询问是否lambda表达式本身可以模板化).
我问你是否可以这样做:
template <class Functor>
struct Foo { };
// ...
Foo<decltype([]()->void { })> foo;
Run Code Online (Sandbox Code Playgroud)
这在例如类模板具有各种参数之类的情况下是有用的,这些参数equal_to通常被实现为单行仿函数.例如,假设我想实例化一个使用我自己的自定义相等比较函数的哈希表.我希望能够说出类似的话:
typedef std::unordered_map<
std::string,
std::string,
std::hash<std::string>,
decltype([](const std::string& s1, const std::string& s2)->bool
{ /* Custom implementation of equal_to */ })
> map_type;
Run Code Online (Sandbox Code Playgroud)
但我在GCC 4.4和4.6上对此进行了测试,但它不起作用,显然是因为lambda表达式创建的匿名类型没有默认构造函数.(我记得有一个类似的问题boost::bind.)是否有某些原因标准草案不允许这样做,或者我错了并且允许但是GCC仅仅落后于它们的实施?
Xeo*_*Xeo 53
我问你是否可以这样做:
Foo<decltype([]()->void { })> foo;
Run Code Online (Sandbox Code Playgroud)
不,你不能,因为lambda表达式不得出现在未计算的情况下(如decltype和sizeof,除其他外).C++ 0x FDIS,5.1.2 [expr.prim.lambda] p2
lambda表达式的评估导致prvalue临时(12.2).这个临时对象称为闭包对象.lambda表达式不应出现在未评估的操作数中(第5条).[注意:闭包对象的行为类似于函数对象(20.8).- end note] (强调我的)
您需要先创建一个特定的lambda,然后使用decltype:
auto my_comp = [](const std::string& left, const std::string& right) -> bool {
// whatever
}
typedef std::unordered_map<
std::string,
std::string,
std::hash<std::string>,
decltype(my_comp)
> map_type;
Run Code Online (Sandbox Code Playgroud)
这是因为每个lambda派生的闭包对象可以有一个完全不同的类型,毕竟它们就像匿名函数.
@Xeo给了你原因,所以我会给你解决的问题.
通常你不想命名一个闭包,在这种情况下,你可以使用std::function,这是一个类型:
typedef std::unordered_map<
std::string,
std::string,
std::hash<std::string>,
std::function<bool(std::string const&, std::string const&)>
> map_type;
Run Code Online (Sandbox Code Playgroud)
请注意,它会准确捕获函数的签名,而不再捕获.
然后你可以在构建地图时简单地编写lambda.
请注意unordered_map,如果更改相等比较,则最好更改哈希以匹配行为.比较相等的对象应具有相同的哈希值.
你完全可以做类似的事情
Foo<decltype([]()->void { })> foo;
Run Code Online (Sandbox Code Playgroud)
由于 c++20 允许在未评估的上下文中使用无状态 lambda。
你不能用一个闭包来做这个,因为状态不包含在类型中.
如果你的lambda是无状态的(没有捕获),那么你应该没问题.在这种情况下,lambda衰减为普通函数指针,您可以将其用作模板参数而不是某些lambda类型.
gcc不喜欢它. http://ideone.com/bHM3n
| 归档时间: |
|
| 查看次数: |
34513 次 |
| 最近记录: |