【问题标题】:Is it possible to use a lambda function for a template parameter?是否可以将 lambda 函数用于模板参数?
【发布时间】:2013-05-26 19:54:07
【问题描述】:

我在查看 std::unordered_map 并发现如果我想使用字符串作为键,我必须创建一个包含仿函数的类。

出于好奇,我想知道是否可以使用 lambda 来代替它。

这是工作原件:

struct hf
{
  size_t operator()(string const& key) const
  {
    return key[0];  // some bogus simplistic hash. :)
  }
}

std::unordered_map<string const, int, hf> m = {{ "a", 1 }};

这是我的尝试:

std::unordered_map<string const, int, [](string const& key) ->size_t {return key[0];}> m = {{ "a", 1 }};

失败并出现以下错误:

exec.cpp: In lambda function:
exec.cpp:44:77: error: ‘key’ cannot appear in a constant-expression
exec.cpp:44:82: error: an array reference cannot appear in a constant-expression
exec.cpp: At global scope:
exec.cpp:44:86: error: template argument 3 is invalid
exec.cpp:44:90: error: invalid type in declaration before ‘=’ token
exec.cpp:44:102: error: braces around scalar initializer for type ‘int’

考虑到这些错误,lamba 似乎与函子有很大的不同,以至于它不是一个常量表达式。对吗?

【问题讨论】:

  • std::hash 专门用于std::string,如果您不想改进/更改哈希,则无需自己提供一些东西。另外,想想你在做什么:std::unordered_map 期望一个 type 作为模板参数,而 lambda 表达式正是这样 - 一个表达式,即一个值,not i> 一种类型。
  • 我发现在我使用的g++编译器中(v4.5.3 with -std=gnu++0x),如果我在使用字符串键。
  • 至于它是一个表达式,是的,我想这就是答案。
  • 4.5.3 对 C++11 的支持很少。不要将此组合用于任何严重的事情。

标签: c++ c++11 lambda


【解决方案1】:

lambda函数的传递方式是:

auto hf = [](string const& key)->size_t { return key[0]; };

unordered_map<string const, int, decltype(hf)> m (1, hf);
                                 ^^^^^^^^^^^^        ^^
                                 passing type        object

decltype(hf) 的输出是一个没有默认构造函数的类类型(被=delete 删除)。所以,你需要通过unordered_map的构造函数传递对象,让它构造lambda对象。

【讨论】:

  • @MM.,像这样:std::unordered_map&lt;string const, int, decltype(hf)&gt; m(1, hf);。第一个参数是初始桶数,第二个是哈希器。遗憾的是,在这种情况下,您不能使用大括号初始化。
  • 有趣,虽然有点作弊,因为您不只是将 lambda 函数作为模板参数传递。事实上,模板参数可以通过一个辅助模板函数一起避免,例如:template&lt;class HASHER&gt; auto make_unordered_map(size_t bucketCount, HASHER const &amp; hf) -&gt; unordered_map&lt;string const, int, decltype(hf)&gt; { return unordered_map&lt;string const, int, decltype(hf)&gt;(bucketCount, hf); },如 here 所示。不过,这很有趣。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-30
  • 2017-08-06
  • 1970-01-01
  • 1970-01-01
  • 2012-12-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多