79553068

Date: 2025-04-03 13:28:36
Score: 1.5
Natty:
Report link

I was toying a lot with this, and so far I have an incomplete answer but some better c++ template wizards can help me. The current code should work for std containers. It still needs work to properly allow things i can get a range from, but this helps me move forward with the desired syntax.

//This structure will take a variant that can contains containers with the same
//value_type (ints, size_t, floats, whatever). It will create a "variant iterator"
//using the variadic template and the iterator_t helper.

template <typename... ContainerTypes>
struct IterableVariantWrapper {

    //This is the part that i have to figure out yet. If the contained type
    //is NOT a container, but i can obtain a range from it, i'd like to 
    //still allow it, but haven't found the way yet.
    using VariantIter = std::variant<const_iterator_t<ContainerTypes>...>;

    //Original variant we want to iterate over.
    const std::variant<ContainerTypes...>& iterable;

    //The iterator
    struct iterator {
        VariantIter iter;

        bool operator!=(
            const iterator& other) const
        {
            return iter != other.iter;
        }
        iterator operator++()
        {
            auto advanceIter = [](auto& v) -> void { ++v; };
            std::visit(advanceIter, iter);
            return *this;
        }
        auto operator*() const
        {
            auto returnElem = [](const auto& v) { return *v; };
            return std::visit(returnElem, iter);
        }
    };

    

    auto begin()
    {
        auto getBegin = [](const auto& v) -> VariantIter {
            VariantIter iter = v.begin();
            return iter;
        };
        return iterator { std::visit(getBegin, iterable) };
    }
    auto end()
    {
        auto getEnd = [](const auto& v) -> VariantIter { return v.end(); };
        return iterator { std::visit(getEnd, iterable) };
    }
};



//Calling this with a variant that contains a container where the contained
//type is the same will build the IterableVariantWrapper structure and provide
//a range-like object
template <typename... ContainerTypes>
auto getVariantRange(
    const std::variant<ContainerTypes...>& variant)
{
    return IterableVariantWrapper { variant };
}

I was thinking that maybe having a function/struct where i could ask the type of the view i can obtain from the iterated objects may be a way to go, but I couldn't get the syntax down. For example having a function for each type that is contained in the variant where the function returns either the same object if it is already a range, or a view derived from it, and then the variant iterator deduces the types from the return type of that function.

As i see, also I still need to figure put how to support actual ranges where the sentinel is a different type too, which i guess will be the next step after the previous paragraph.

A link to a working example using this: https://godbolt.org/z/qhrbP1se6

Any comment for further improvement is greatly appreciated.

Reasons:
  • Blacklisted phrase (1): appreciated
  • Blacklisted phrase (1): help me
  • Long answer (-1):
  • Has code block (-0.5):
  • Self-answer (0.5):
  • Low reputation (0.5):
Posted by: Carlos