c++ - Lambda 表达式作为类模板参数

标签 c++ templates lambda c++11

可以将 lambda 表达式用作作为类模板参数吗? (请注意,这是一个与 this one 非常不同的问题,后者询问是否可以对 lambda 表达式本身进行模板化。)

我问你是否可以这样做:

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

这在某些情况下很有用,例如,类模板具有各种参数,如 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 上对此进行了测试,但它不起作用,显然是因为 lambda 表达式创建的匿名类型没有默认构造函数。 (我记得 boost::bind 有一个类似的问题。)是否有某种原因草案标准不允许这样做,或者我错了,它是允许的,但 GCC 只是落后于他们的实现?

最佳答案

从 C++20 开始,此答案现已过时。 C++20 在未评估的上下文中引入了无状态 lambda 1 :

This restriction was originally designed to prevent lambdas from appearing in signatures, which would have opened a can of worm for mangling because lambdas are required to have unique types. However, the restriction is much stronger than it needs to be, and it is indeed possible to achieve the same effect without it

一些限制仍然存在(例如,lambdas 仍然不能出现在函数签名上),但所描述的用例现在完全有效,不再需要声明变量。


I'm asking if you can do something like:

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

不,你不能,因为 lambda 表达式不应出现在未计算的上下文中(例如 decltypesizeof 等)。 C++0x FDIS,5.1.2 [expr.prim.lambda] p2

The evaluation of a lambda-expression results in a prvalue temporary (12.2). This temporary is called the closure object. A lambda-expression shall not appear in an unevaluated operand (Clause 5). [ Note: A closure object behaves like a function object (20.8).—end note ] (emphasis mine)

您需要先创建一个特定的 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 派生的闭包对象都可以有完全不同的类型,它们毕竟就像 匿名 函数。

关于c++ - Lambda 表达式作为类模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5849059/

相关文章:

c++ - 使用 Visual Studio 远程 GDB 调试器时出错

c++ - Qt Installer Framework - 读取下载的包版本

c++ - std::tuple_element 可以兼作通用模板参数检索器吗?

c++ - 调用模板函数的常规方式

c++ - 让编译器最终选择使用哪种类型

c++ - 为什么在 C++14 中使用 std::bind 而不是 lambda?

c++ - 在没有上下文参数的情况下将有状态 lambda 传递给 C 样式函数

c++ - C++ 异常处理程序的一个奇怪问题

c++ - 由于多线程(使用 boost 库)导致的 seg 错误

java - 如何从 StackFrameStream 中只获取前两个 stackFrames?