I have the need to map some elements to certain ids, elementId's to starting node ids in a graph. I need to store just ids of the elements so generally we could work with just sets or vectors of size_t. Generally there are millions of elements that are added in batches to be mapped to a single id. This is why we use specific representations for typical assignments and store it in a variant.
For example
//std::set -> random set of elements
//Interval -> elements from a starting id up to a final id
//Single -> just a single element
using VariantSet = std::variant<std::set, Interval, Single>;
//This is the vector containing the mapping
std::vector< std::tuple<VariantSet, size_t> > mapping;
We started using std::ranges on several parts and the general result have been great, but i got stuck with the variant. I'd like to get a range from a function so I could iterate over the elements that are mapped to a given id.
For example:
for (auto elementId: getMappedElements(mapping, interestingId){
do_something_with_the_element(elementId);
}
The problem I found is that i have to use std::visit to retrieve the range from the underlying object stored in the variant, but that range will be a different type depending on which real container is iterated. For example the Singular container was returning views::single while the Interval was returning iota. Of course, this enrages the compiler as the visitors must return the same type for every possible type in the variant and of course the wrapping function getMappedElements can't return multiple types either.
Currently we are passing the function "do_something_with_the_element" as a lambda so we can do a visitor that in turns applies this lambda, but it messes up some uses that we had in mind. Is there a way to achieve this "polymorphic" range so i can actually return a range that later can be further composed (very likely a transform)
Any help is appreciated.
EDIT: Link to example: https://godbolt.org/z/nx41v3Eqb . It was buried in the comments, copied here for better visibility.
for (auto elementId: getMappedElements(mapping, interestingId){ do_something_with_the_element(elementId); }->for (auto &v: getMappedVariants(mapping, interestingId){ do_something_with_variant(v); }