gpt4 book ai didi

c++ - 如何避免重复使用 "indices trick"?

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:07:26 27 4
gpt4 key购买 nike

我有一个名为 memory_region 的类,有点像未类型化的 gsl::span (即它本质上是一个 void* 和一个 size_t ),我也将其用于类型删除。因此它有一个 as_span<T>()方法。

对于这个类,我有一个 std::unordered_map<std::string, memory_region> my_map - 它用于在我的不共享 header 的代码部分之间传递类型删除的跨度,因此它们无法了解彼此的类型。对其中之一的典型访问如下所示:

auto foo = my_map.at("foo").as_span<bar_t>();

这对于具有一组固定缓冲区、类型和名称的代码来说效果很好。但是 - 当我的代码缓冲区依赖于模板参数包时,事情就变得棘手了。现在,我实现了一个

std::string input_buffer_name(unsigned input_buffer_index);

函数,所以如果我有一个索引序列和我的参数包我可以做,例如

template<typename Ts..., std::size_t... Indices>
my_function(std::unordered_map<std::string, memory_region>& my map) {
compute_stuff_with_buffers(
my_map.at(input_buffer_name(Indices)).as_span<Ts>()...
);
}

(这是臭名昭著的 indices trick 的变体;请注意,同一类型可能会在包中多次出现,因此我不能“将类型包装在一个元组中”并按类型访问它。)

但问题是——我的代码在模板参数中没有那个索引序列;其中大部分仅基于类型的参数包进行模板化。所以我发现自己一直在编写“辅助函数/方法”以便能够使用该索引序列,例如:

template<typename Ts..., std::size_t... Indices>
my_function_helper(
std::unordered_map<std::string, memory_region>& my map
std::index_sequence<Indices...> /* unused */)
{
compute_stuff_with_buffers(
my_map.at(input_buffer_name(Indices)).as_span<Ts>()...
);
}

template<typename Ts...>
my_function(std::unordered_map<std::string, memory_region>& my map) {
my_function_helper(
my_map, std::make_index_sequence<sizeof...(Ts)> {}
);
}

我该怎么做,才不会涉及那么多代码重复?

最佳答案

在这种情况下,您可以使用数组形式的简单包扩展:

template<typename... Ts>
void my_function(std::unordered_map<std::string, memory_region>& my_map) {
using swallow = int[];
unsigned i = 0;
(void)swallow{0, (my_map.at(input_buffer_name(i++)).as_span<Ts>(), 0)...};
}

Demo

包扩展将按顺序展开 ([temp.variadic]),并且也会按顺序(从左到右)求值,因为我们使用的是花括号初始化列表(一个未使用的整数数组):[dcl.init.聚合]

When an aggregate is initialized by an initializer list [...] the elements of the initializer list are taken as initializers for the elements of the aggregate, in order.


回复:

But what if I need to use input_buffer_name(i) twice? e.g. if I need to use { input_buffer_name(index), my_map.at(input_buffer_name(index).as_span<Ts>()) }

我想我们可以利用逻辑与将从左到右排序的事实 ([expr.log.and]),并且 bool 值也可以提升为 int。 :

template<typename... Ts>
void my_function_v2(std::unordered_map<std::string, memory_region>& my_map) {
using swallow = int[];
unsigned i = 0;
(void)swallow{0, ((std::cout<< input_buffer_name(i) << std::endl, true) && (my_map.at(input_buffer_name(i++)).as_span<Ts>(), true))...};
}

Demo 2

关于c++ - 如何避免重复使用 "indices trick"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45813673/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com