首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何避免重复使用“索引技巧”?

如何避免重复使用“索引技巧”?
EN

Stack Overflow用户
提问于 2017-08-22 17:22:27
回答 1查看 387关注 0票数 4

我有一个名为memory_region的类,它有点像一个非类型化的gsl::span (即它本质上是一个void*和一个size_t),我还用它来进行类型擦除。因此,它有一个as_span<T>()方法。

有了这个类,我有了一个std::unordered_map<std::string, memory_region> my_map --它用来在我的代码中不共享头的部分之间传递类型擦除的跨度,所以它们不能知道彼此的类型。对其中之一的典型访问如下所示:

代码语言:javascript
复制
auto foo = my_map.at("foo").as_span<bar_t>();

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

代码语言:javascript
复制
std::string input_buffer_name(unsigned input_buffer_index);

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

代码语言:javascript
复制
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的变体;请注意,相同的类型可能会在包中出现多次,因此我不能“将类型包装在元组中”并按类型访问它。)

不过,问题是-我的代码在模板参数中没有索引序列;大多数都是在类型的参数包上模板化的。因此,我发现自己一直在编写“辅助函数/方法”,以便能够使用该索引序列,例如:

代码语言:javascript
复制
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)> {}
    );
}

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

EN

回答 1

Stack Overflow用户

发布于 2017-08-22 20:32:45

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

代码语言:javascript
复制
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.aggr

当聚合由初始化器列表初始化时...按照顺序,初始化器列表的元素被用作聚合元素的初始化器。

回复:

但是如果我需要使用input_buffer_name(i)两次怎么办?例如,如果我需要使用{ input_buffer_name(index), my_map.at(input_buffer_name(index).as_span<Ts>()) }

我认为我们可以利用这样一个事实,即逻辑AND将从左到右排序(expr.log.and),并且布尔值也可以提升为int

代码语言:javascript
复制
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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45813673

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档