c++ - Consexpr lambda 参数
问题描述
是否可以有一个带有 constexpr 参数的 lambda?是否可以使以下示例起作用?
ForEach
下面提供的函数调用给定的 lambda 3 次,索引为 0、1、2:
template <class Func, std::size_t... index>
inline constexpr void ForEach(Func && f, std::index_sequence<index...>)
{
(f(index), ...);
}
template <class Func>
inline constexpr void ForEach(Func && f)
{
ForEach(f, std::make_index_sequence<3>());
}
所以下面的代码
ForEach([](size_t index)
{
std::cout << index << ' ' << std::endl;
});
输出 0、1、2。
但是以下尝试打印元组元素的代码需要index
是 constexpr:
auto t = std::make_tuple(1, 2.0, std::string("abc"));
ForEach([&t](size_t index)
{
std::cout << std::get<index>(t) << ' ' << std::endl;
});
因此无法编译,请参见live example。有可能以index
某种方式制作 constexpr 吗?
EDIT1:有一个工作示例,其中将 lambda 参数用作模板参数:
void Set(Tuple& val, size_t index, Variant const& elem_v)
{
mp_with_index<std::tuple_size_v<Tuple>>(
index,
[&](auto I){
std::visit([&](auto const& alt){
if constexpr (std::is_assignable_v<
std::tuple_element_t<Tuple, I>,
decltype(alt)>)
{
std::get<I>(val) = alt;
} else {
throw /* something */;
}
}, elem_v);
});
}
为什么这个编译,但我的示例代码没有?
解决方案
在这:
ForEach([&t](size_t index)
{
std::cout << std::get<index>(t) << ' ' << std::endl;
});
index
不是常量表达式。这只是一个变量。函数参数不是 constexpr。
但是,如果我们进行ForEach
了一些调整(以与您链接的我的示例相同的方式工作):
template <class Func, std::size_t... index>
inline constexpr void ForEach(Func && f, std::index_sequence<index...>)
{
(f(std::integral_constant<std::size_t, index>()), ...);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// instead of just index
}
ForEach([&t](auto index)
{
std::cout << std::get<index>(t) << ' ' << std::endl;
});
然后这有效,因为index
不再是for varioussize_t
的不同实例,而是不同的实例。这种类型看起来像:std::integral_constant<size_t, V>
V
template<class T, T v> struct integral_constant { static constexpr T value = v; typedef T value_type; typedef integral_constant type; // using injected-class-name constexpr operator value_type() const noexcept { return value; } constexpr value_type operator()() const noexcept { return value; } //since c++14 };
将 a 转换std::integral_constant<size_t, V>
为 asize_t
调用constepxr operator size_t()
,这不涉及从该对象本身(它是一个空类型)读取任何状态,因此它被允许作为一个常量表达式。
另一种看待它的方式是,我们将值编码为类型(可以作为常量表达式检索)而不是值(不能)。
推荐阅读
- angular - Angular 通用 SSR,第一次调用查找用户的 ip 来自服务器而不是客户端?
- cassandra - 在 CASSANDRA 中,无法创建具有精度和比例值的表
- android - 如何在 CameraX API 中的相机之间切换?
- angular - 无法读取未定义的属性“单位”
- java - 如何在 String 和 JsonNode 之间转换使用 toString() 方法和 JsonNode(String) 构造函数
- javascript - 文档方法引用在 JavaScript 中不起作用
- angular - NPM 运行包为 Angular Element 提供错误
- angular - 如何在父组件Angular 7中获取在HTML中处于活动状态的子组件名称
- javascript - 在给定正数、负数和零数的数组的情况下返回百分比数组
- google-maps - 在离子谷歌地图中添加多个标记