c++ - 为什么在爆炸 std::tuple 时需要 std::integral_constant?
问题描述
#include <iostream>
#include <tuple>
#include <iostream>
#include <utility>
template <std::size_t... Idx>
auto make_index_dispatcher(std::index_sequence<Idx...>)
{
return [](auto&& f) { (f(std::integral_constant<std::size_t, Idx>{}), ...); };
}
template <std::size_t N>
auto make_index_dispatcher()
{
return make_index_dispatcher(std::make_index_sequence<N>{});
}
template <typename Tuple, typename Func>
void for_each(Tuple&& t, Func&& f)
{
constexpr auto n = std::tuple_size<std::decay_t<Tuple>>::value;
auto dispatcher = make_index_dispatcher<n>();
dispatcher([&f, &t](auto idx) { f(std::get<idx>(std::forward<Tuple>(t))); });
}
int main()
{
for_each(std::make_tuple(1, 42.1, "hi"), [](auto&& e) {std::cout << e << ","; });
}
问题1>为什么我必须在下面的语句中使用std::integral_constant<std::size_t, Idx>{}
而不是简单的?Idx
根据我的理解,std::integral_constant<std::size_t, Idx>
是一种类型。std::integral_constant<std::size_t, Idx>{}
的值是真的Idx
吗?
// 好的
template <std::size_t... Idx>
auto make_index_dispatcher(std::index_sequence<Idx...>)
{
return [](auto&& f) { (f(std::integral_constant<std::size_t, Idx>{}), ...); };
}
// 错误
template <std::size_t... Idx>
auto make_index_dispatcher(std::index_sequence<Idx...>)
{
return [](auto&& f) { (f(Idx), ...); };
}
std::get
预期的编译时常量表达式 whileIdx
不是编译时常量表达式是真的吗?
问题2>为什么我们不能通过std::index_sequence
引用传递?
// 错误:
auto make_index_dispatcher(std::index_sequence<Idx...>&)
谢谢
解决方案
为什么我必须在以下语句中使用 std::integral_constant{} 而不是简单的 Idx?
因为函数参数从来都不是常量表达式。您可以简单地将索引作为非类型模板参数传递,它们是常量表达式。这特别适用于 C++20 模板 lambda:
template <std::size_t... Idx>
auto make_index_dispatcher(std::index_sequence<Idx...>)
{
return [](auto&& f) { (f.template operator()<Idx>(), ...); };
}
template <typename Tuple, typename Func>
void for_each(Tuple&& t, Func&& f)
{
constexpr auto n = std::tuple_size<std::decay_t<Tuple>>::value;
auto dispatcher = make_index_dispatcher<n>();
dispatcher([&f, &t]<auto Idx>(){ f(std::get<Idx>(std::forward<Tuple>(t))); });
}
为什么我们不能通过引用传递 std::index_sequence?
您可以,但您需要像使用任何其他非const
引用一样使用左值调用您的函数。这编译:
template <std::size_t... Idx>
auto make_index_dispatcher(std::index_sequence<Idx...>&)
{
}
int main()
{
std::index_sequence<> is;
make_index_dispatcher(is);
}
而且,它完全没用。
此外,您的整个代码可以简单地是:
int main()
{
std::apply([](auto&&... xs)
{
((std::cout << xs << ','), ...);
}, std::make_tuple(1, 42.1, "hi"));
}
推荐阅读
- reactjs - Imported node_modules css not working in webpack
- c - twosum problem when array elements are negative
- python - Regex for finding if a phrase is present in any location in a string
- ios - 我需要保留证书签名请求 (CSR) 文件吗?
- arrays - 如何将元素添加到 IDL 中可用于绘图的数组中?
- apache-kafka - Is there a Telegraf plugin which takes in queries to read data from Influxdb and then post them on a kafka topic using the Kafka output plugin?
- reactjs - 如何在 react-big-calander onSelectEvent 的警报中显示两个事件项
- r - 是否可以在闪亮中部署预训练的机器学习模型?
- javascript - flask just refresh templated portion of page
- typescript - 打字稿将动态变量分配给地图对象