【问题标题】:Does using lambda as constructor argument requires C++ 17?使用 lambda 作为构造函数参数是否需要 C++ 17?
【发布时间】:2020-05-11 22:00:14
【问题描述】:

我有以下在其构造函数中接受 lambda 的类

template<typename MAPPER>
    class MapHead {
    protected:
        MAPPER mapper_;
    public:
        MapHead(MAPPER mapf)
                : mapper_(mapf) {}

        template<typename IN>
        auto call(IN input) -> decltype(mapper_(input)) {
            return mapper_(input);
        }
    };

这个类的目的是保存 lambda 以进行惰性求值。我像这样测试它

auto node = MapHead([](int a) {
                   ^-- Error here
    return (uint32_t) a * 2;
});

int value = 2;
EXPECT_EQ(4, node.call(value));

在使用 gcc 和 C++ 14 编译代码时,我在标记处出现错误,提示“使用类模板 'MapHead' 需要模板参数”。

由于 lambda 没有命名类型,我无法手动为其提供模板参数,如 MapHead&lt;LambdaType&gt;

切换到 C++17 时,代码会编译,因为 C++17 会自动从 lambda 推导模板类型。但我看到人们在 C++0x 中使用 lambda 作为函数参数,如 this answer 中所述。

我的问题是:切换到 C++17 是解决此问题的唯一方法吗?还是我缺少什么?

【问题讨论】:

  • C++0x 具有自动函数模板类型推导。 C++17增加了自动class模板类型推导。

标签: c++ templates lambda


【解决方案1】:

c++17之前没有类模板参数推导,所以你必须指定模板参数。

不是很漂亮,但这很有效:

auto lambda = [](int a) { 
        return (uint32_t) a * 2;
};
auto node = MapHead<decltype(lambda)>(lambda);

您可以将其包装在工厂函数中以进行参数推导。

【讨论】:

  • 谢谢。这确实有效,但在 C++ 17 下它看起来更优雅。我会接受你的回答。顺便说一句,如果代码编译良好并且所有测试用例都通过,我有什么理由不升级到 C++ 17?
  • 我认为您应该尽可能使用最新版本。如果没有理由支持旧的 c++ 标准,请不要支持它们。
猜你喜欢
  • 1970-01-01
  • 2013-10-25
  • 1970-01-01
  • 2014-06-13
  • 2016-07-19
  • 2014-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多