是否可以使lambda签名中的模板变量通用?

时间:2018-10-20 21:09:07

标签: c++ templates lambda c++17 generic-lambda

假设您有一个函数,可以接受任何类型的std::vector并以某种方式对其进行处理:

template<typename T>
void foo(std::vector<T> &vec) {
    // work with vec
}

C++14起,我们就能使用lambda实现相同的目的。在这种情况下,我们将它们称为“通用lambda” ,因为我们向它们引入了类似模板的推论:

auto foo_lambda = [](std::vector<auto> &vec) {
    // work with vec
};

但是我们的选择似乎仅限于我。假设我不仅必须引入类型推导,而且还需要引入模板值。例如,让我们将std::vector更改为std::array

template<typename T, std::size_t size>
void foo(std::array<T, size> &arr) {
    // work with arr
}

在处理模板函数时,我们可以引入一个模板值,该值可用于满足参数的需要。整洁。

我想用通用lambda实现相同的功能,但我无法做到。

是否有一种方法可以向lambda表达式引入相似的推导值,以便与上述std::array函数的第二版相似,任何foo()都可以与该lambda一起使用?

编辑:如 Evg 的注释所述,我的vector<auto>语法是非标准的GCC扩展名。有关详细信息,请参见this answer,指的是this document

3 个答案:

答案 0 :(得分:5)

您可以使用一些专用的类型特征:

#include <type_traits>
#include <utility>
#include <array>

template<typename x_Whatever> struct
is_array: ::std::false_type {};

template<typename x_Item, ::std::size_t x_items_count> struct
is_array<::std::array<x_Item, x_items_count>>: ::std::true_type {};

int main()
{
    auto Do_SomethingWithArray
    {
        [](auto & should_be_array)
        {
            static_assert
            (
                is_array
                <
                    ::std::remove_reference_t<decltype(should_be_array)>
                >::value
            );            
        }
    };
    ::std::array<int, 3> a{};
    Do_SomethingWithArray(a); // Ok
    int x{};
    Do_SomethingWithArray(x); // error
}

online compiler

答案 1 :(得分:3)

  

是否有一种方法可以向lambda表达式引入类似的推导值,以便任何std :: arrays都可以与上述lambda一起使用,类似于上面的foo()函数的第二个版本?

是的。但是,不幸的是,(大概)从C ++ 20开始

auto foo_lambda = []<typename T, std::size_t S>(std::array<T, S> & arr)
 { /* ... */ };

在C ++ 14 / C ++ 17中,您可以使用decltype()提取所需的内容。

std::array情况下,

auto foo_lambda = [](auto & arr)
 {
   using T = typename std::remove_reference_t<decltype(arr)>::value_type;
   std::size_t S = arr.size();

   // ...
 };

对于其他类型,您可以开发自定义类型特征以从decltype(arr)开始提取所需的元素。

答案 2 :(得分:0)

您的const responseText = `<div> <ab type="transcription"><!` + `--This is a comment--></ab> </div>`; const doc = new DOMParser().parseFromString(responseText, 'text/html'); const text = doc.querySelector('ab').childNodes[0].textContent; document.querySelector('#comment').value = text;语法错误。

您可以使用辅助函数和特征类在lambda的返回类型/主体中拆分<textarea id="comment"></textarea>参数的类型。

\ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0428r1.pdf是将vector<auto>添加到语言的建议。诸如此类的东西应该放在中。

我之前做过两次lambda:

auto

并像这样使用:

[]<template T>( std::vector<T>& ){}

我们使用值作为模板类型参数。