Lambdaexpression式作为类模板参数

可以使用lambdaexpression式作为类模板参数吗? (请注意,这是一个非常不同的问题,它会询问一个lambdaexpression式本身是否可以模板化。)

我问你是否可以做这样的事情:

template <class Functor> struct Foo { }; // ... Foo<decltype([]()->void { })> foo; 

这在例如一个类模板具有不同的参数(如equal_to或者其他的东西)的情况下是有用的,这些参数通常被实现为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; 

但是我在GCC 4.4和4.6上testing了这个,并且不起作用,显然是因为由lambdaexpression式创build的匿名types没有默认的构造函数。 (我记得与boost::bind类似的问题。)是否有一些原因,标准草案不允许这样做,或者我错了,它是允许的,但GCC只是落后于他们的实施?

我问你是否可以做这样的事情:

 Foo<decltype([]()->void { })> foo; 

不可以,因为lambdaexpression式不应出现在未评估的上下文中(如decltypesizeof等)。 C ++ 0x FDIS,5.1.2 [expr.prim.lambda] p2

lambdaexpression式的评估导致临时值(12.2)。 这个临时的被称为闭包对象。 lambdaexpression式不应出现在未评估的操作数中 (第5章)。 [注:闭包对象的行为就像一个函数对象(20.8)。 – 注释] (重点是我的)

你需要先创build一个特定的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; 

这是因为每个lambda派生的闭包对象可以有一个完全不同的types,毕竟它们就像匿名函数一样。

@Xeo给你的理由,所以我会给你的工作。

通常情况下,您不希望命名闭包,在这种情况下,您可以使用std::function ,它是一个types:

 typedef std::unordered_map< std::string, std::string, std::hash<std::string>, std::function<bool(std::string const&, std::string const&)> > map_type; 

请注意,它捕获function的签名,没有更多。

然后,你可以简单地写在构build地图的lambda。

请注意,对于unordered_map ,如果更改等同比较,则最好更改散列以匹配行为。 比较相等的对象应该具有相同的散列。

你不能用闭包来做到这一点,因为状态不包含在types中。

如果你的lambda是无状态的(没有捕获),那么你应该没问题。 在这种情况下,lambda衰减到一个普通的函数指针,你可以使用它作为模板参数而不是lambdatypes。

海湾合作委员会虽然不喜欢它。 http://ideone.com/bHM3n

您将不得不使用运行时抽象types,如std::function ,或者将types创build为局部variables或作为模板类的一部分。