How to avoid reusing "index tricks"?

I have a class with a name memory_regionthat looks like untyped gsl::span(i.e. essentially a void*and a size_t), which I also use to erase the type. So he has a method as_span<T>().

With this class I have std::unordered_map<std::string, memory_region> my_map- which is used to pass erased lines between parts of my code that do not share headers, so they cannot know each other's types. Typical access to one of them is as follows:

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

This works great with code that has a fixed set of buffers, types, and names. But - it all gets complicated when my code buffers depend on a package of template parameters. Now i have implemented

std::string input_buffer_name(unsigned input_buffer_index);

therefore, if I have an index sequence and my package of parameters, I can do, for example

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>()...
    );
}

(This is a variation on the infamous index trick , note that the same type can appear more than once in a package, so I cannot "wrap types in a tuple" and get it by type.)

The fact is that - my code does not have this index sequence in the template parameters; most of them are templates only for the type parameter package. Therefore, I always find "helper functions / methods" to be able to use this index sequence, for example:

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)> {}
    );
}

What can I do instead that will not include as much code duplication?

+4
1

:

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]

[...], .


Re:

, __ (i)? { input_buffer_name(index), my_map.at(input_buffer_name(index).as_span<Ts>()) }

, , ([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))...};
}

2

+2

Source: https://habr.com/ru/post/1684211/


All Articles