Below is a minimal example of an attempt to use the std::ranges
library to look at a map<int,...>
and return only the first elements such that the int
is contiguous starting at one. However, the code crashes while looping through the names at for (auto& name : names)
giving ITERATOR LIST CORRUPTED (msvc 2019). I assume i somehow have a reference to a temporary, but I cannot figure out where.
Can anyone help me identify the mistake?
NOTE: I know this is solution not great - it will keep checking after an element fails instead of ending early, and the range only works once, c++23 can use views::zip()
with an unbounded views::iota
and views::take_while
instead.
#include <iostream>
#include <map>
#include <ranges>
struct NameHolder
{
auto contiguous_indexed_names()
{
return grouped_name_sequences | std::views::transform([](auto& group_names)
{
auto sequential_names = group_names.second | std::views::filter([expected = 1](auto& idx_name) mutable
{
return idx_name.first == expected++;
}) | std::views::values;
return std::forward_as_tuple(group_names.first, sequential_names);
// solution: return std::tuple<decltype(group_names.first)&, decltype(sequential_names)>(group_names.first, sequential_names);
});
}
void add(const std::string& group, int sequence, std::string name)
{
grouped_name_sequences[group].emplace(sequence, std::move(name));
}
std::map<std::string, std::map<int, std::string>> grouped_name_sequences;
};
int main()
{
NameHolder grouped_names;
grouped_names.add("Group1", 1, "A");
grouped_names.add("Group1", 2, "B");
grouped_names.add("Group1", 4, "D");
for (auto [group, names] : grouped_names.contiguous_indexed_names())
{
for (auto& name : names)
{
// expect only "A", "B"
std::cout << name << "\n";
}
}
return 0;
}
You are returning a reference to a local variable.
auto sequential_names = group_names.second | std::views::filter([expected = 1](auto& idx_name) mutable
{
return idx_name.first == expected++;
}) | std::views::values;
return std::forward_as_tuple(group_names.first, sequential_names);
Above, sequential_names
is a view that you have created on the stack.
std::forward_as_tuple
produces a reference to this stack variable, which you are returning.
Accessing this dangling reference is Undefined Behavior.