【发布时间】:2018-01-30 12:09:00
【问题描述】:
我有一个名为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)> {}
);
}
我能做些什么,而不涉及那么多代码重复?
【问题讨论】:
-
没有真正解决索引技巧,但大部分代码似乎是多余的。
unordered_map或input_buffer_name都不是必需的,因为您实际上是使用索引提取memory_region项目。所以在我看来你可以使用tuple作为容器。此外,如果Tspack 不包含重复类型,那么您可以使用标记元组作为容器并直接按类型从中提取项目。compute_stuff_with_buffers(regions.at<Ts>().as_span<Ts>()...); -
@VTT:创建
my_map的代码不知道使用my_map的代码会对哪些类型感兴趣。此外,Ts 经常包含重复的类型。将编辑以提及最后一点。 -
@VTT:此外,代码的其他部分需要能够在不知道任何类型的情况下迭代
buffers,并且buffers源自不同的实例化。 -
小请求:能否修复代码中的语法错误,并链接到可编译的示例?真的会帮助那些来到这里的人快速上手并更快地回答您的问题。
标签: c++ c++14 variadic-templates idioms index-sequence