是否可以使 lambda 签名中的模板变量通用?
Is it possible to make a template variable in lambda signature generic?
假设您有一个函数接受任何类型的 std::vector
并以某种方式处理它:
template<typename T>
void foo(std::vector<T> &vec) {
// work with vec
}
自 C++14
以来,我们可以使用 lambda 实现相同的目的。在这种情况下,我们称它们为 generic lambdas,因为我们向它们引入了类似模板的推导:
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
都可以与上述 lambda 一起使用,类似于上面 foo()
函数的第二个版本?
编辑:正如 Evg 的评论所述,我的 vector<auto>
语法是非标准 GCC 扩展。有关详细信息,请参阅 this answer referring to this document。
您可以使用一些专用的类型特征:
#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
}
Is there a way to introduce a similar, deduced value to a lambda expression so any std::arrays can be used with said lambda, similarily to the second version of the foo() function above?
是的。但是,不幸的是,(大概)从 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)
.
开始提取所需的元素
您的 vector<auto>
语法错误。
您可以使用辅助函数和特征 类.
分解 lambda return type/body 中 auto
参数的类型
\http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0428r1.pdf is a proposal to add []<template T>( std::vector<T>& ){}
to the lamguage. Something like it should be in c++20.
我以前做过双 lambdas:
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>{} );
我们使用值作为模板类型参数。
假设您有一个函数接受任何类型的 std::vector
并以某种方式处理它:
template<typename T>
void foo(std::vector<T> &vec) {
// work with vec
}
自 C++14
以来,我们可以使用 lambda 实现相同的目的。在这种情况下,我们称它们为 generic lambdas,因为我们向它们引入了类似模板的推导:
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
都可以与上述 lambda 一起使用,类似于上面 foo()
函数的第二个版本?
编辑:正如 Evg 的评论所述,我的 vector<auto>
语法是非标准 GCC 扩展。有关详细信息,请参阅 this answer referring to this document。
您可以使用一些专用的类型特征:
#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
}
Is there a way to introduce a similar, deduced value to a lambda expression so any std::arrays can be used with said lambda, similarily to the second version of the foo() function above?
是的。但是,不幸的是,(大概)从 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)
.
您的 vector<auto>
语法错误。
您可以使用辅助函数和特征 类.
分解 lambda return type/body 中auto
参数的类型
\http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0428r1.pdf is a proposal to add []<template T>( std::vector<T>& ){}
to the lamguage. Something like it should be in c++20.
我以前做过双 lambdas:
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>{} );
我们使用值作为模板类型参数。