5

假设您有一个函数,它采用std::vector任何类型并以某种方式处理它:

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

因为C++14,我们可以用 lambdas 实现同样的目标。在这种情况下,我们称它们为泛型 lambda,因为我们为它们引入了类似模板的推导:

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

但我们的选择对我来说似乎非常有限。假设我不仅要引入类型推导,还需要引入模板值。例如,让我们更改std::vectorstd::array

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

在处理模板函数时,我们可以引入一个模板值,它可以用来匹配参数的需要。整洁的。

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

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

编辑:正如Evg评论中所述,我的vector<auto>语法是非标准的 GCC 扩展。有关详细信息,请参阅此文档的答案

4

3 回答 3

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
}

在线编译器

于 2018-10-20T21:24:29.523 回答
4

有没有办法向 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).

于 2018-10-20T21:25:06.870 回答
0

你的vector<auto>语法是错误的。

auto您可以使用辅助函数和特征类在 lambda 的返回类型/主体中拆分参数的类型。

\ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0428r1.pdf是添加[]<template T>( std::vector<T>& ){}到语言中的建议。类似的东西应该在中。

我之前做过双 lambda:

template<class T>struct tag_t{using type=T;};
template<class T>constexpr tag_t<T> tag{};
template<class Tag>using type_t=typename Tag::type;

auto f = [](auto tag_T){ return []( std::vector<type_t<decltype(tag_T)>> const& v){ /* code */ }; };

并使用:

f(tag<int>)( std::vector<int>{} );

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

于 2018-10-20T21:29:16.777 回答