Raildex
Raildex

Reputation: 4747

Returning range of different containers

I have multiple containers with the same element type T. I would like to select one of the containers depending on a enum.

I tried something like this:

auto range = [category,system]() -> auto {
    switch(category) {
        case sound_category::voice:
            return std::ranges::views::all (system->dialogue_voices); // could be std::array
        case sound_category::mono:
            return std::ranges::views::all (system->mono_voices); // could be std::vector
        case sound_category::music:
            return std::ranges::views::all (system->music_voices); // could be std::list
        default:
            return std::ranges::views::all (system->sfx_voices); // could be std::deque
    }
}();

but that will result in a compiler error, since the deduced type in the cases is different.

Is there some way to achieve that?

Upvotes: 2

Views: 260

Answers (3)

Jarod42
Jarod42

Reputation: 217283

ranges-v3 has any_view for type erasure view.

So it would be something like:

auto range = [category,system]() -> ranges::v3::any_view<Voice>
{
    switch(category) {
        case sound_category::voice:
            return std::ranges::views::all (system->dialogue_voices); // could be std::array
        case sound_category::mono:
            return std::ranges::views::all (system->mono_voices); // could be std::vector
        case sound_category::music:
            return std::ranges::views::all (system->music_voices); // could be std::list
        default:
            return std::ranges::views::all (system->sfx_voices); // could be std::deque
    }
}();

Upvotes: 2

Artyer
Artyer

Reputation: 40811

Instead of something like:

auto range = [category,system]() -> auto {
    switch(category) {
        case sound_category::voice:
            // ...
    }
}();
// stuff with range

You can use a visitor pattern:

auto visitor = [&](const auto& range) {
    // stuff with range
};
switch (category) {
    case sound_category::voice:
        return visitor(system->dialogue_voices);
    case sound_category::mono:
        return visitor(system->mono_voices);
    // ...
}

Upvotes: 1

KamilCuk
KamilCuk

Reputation: 141040

Use a subrange from two iterators.

#include <ranges>
#include <array>
int main() {
    std::array<int, 2> a;
    std::array<int, 3> b;
    auto c = std::ranges::subrange<int*>(a.begin(), a.end());
    c = std::ranges::subrange<int*>(b.begin(), b.end());
}

Upvotes: 1

Related Questions