我有一个名为memory_region的类,它有点像一个非类型化的gsl::span (即它本质上是一个void*和一个size_t),我还用它来进行类型擦除。因此,它有一个as_span<T>()方法。
有了这个类,我有了一个std::unordered_map<std::string, memory_region> my_map --它用来在我的代码中不共享头的部分之间传递类型擦除的跨度,所以它们不能知道彼此的类型。对其中之一的典型访问如下所示:
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)> {}
);
}我该怎么做,才不会涉及这么多的代码重复呢?
发布于 2017-08-22 20:32:45
在这种情况下,您可以使用数组形式的简单包扩展:
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)...};
}包扩展将按顺序(temp.variadic)展开,并按顺序(从左到右)进行计算,因为我们使用了带括号的初始化器列表(一个未使用的整数数组):dcl.init.aggr
当聚合由初始化器列表初始化时...按照顺序,初始化器列表的元素被用作聚合元素的初始化器。
回复:
但是如果我需要使用input_buffer_name(i)两次怎么办?例如,如果我需要使用
{ input_buffer_name(index), my_map.at(input_buffer_name(index).as_span<Ts>()) }
我认为我们可以利用这样一个事实,即逻辑AND将从左到右排序(expr.log.and),并且布尔值也可以提升为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))...};
}https://stackoverflow.com/questions/45813673
复制相似问题