I have a std::vector
of std::variant
elements with type int
or std::set<int>
. I want to loop over this vector and insert
an extra item if the iterated element is of type std::set<int>
. However, it seems that querying the index at run-time is not allowed. How can I achieve this?
#include <variant>
#include <set>
#include <vector>
int main()
{
using Variants = std::variant<int, std::set<int>>;
std::vector<Variants> var_vec;
var_vec.push_back(999);
std::set<int> a = {0,1,2};
var_vec.push_back(a);
for (int i = 0; i < var_vec.size(); ++i)
{
// if the element var_vec[i] is of type std::set<int>
if (var_vec[i].index() == 1) var_vec[i].insert(888); // !ERROR! How to achieve this?
}
return 0;
}
Error message:
error: '__gnu_cxx::__alloc_traits<std::allocator<std::variant<int, std::set<int, std::less<int>, std::allocator<int> > > >, std::variant<int, std::set<int, std::less<int>, std::allocator<int> > > >::value_type' {aka 'class std::variant<int, std::set<int, std::less<int>, std::allocator<int> > >'} has no member named 'insert'
There's nothing wrong with calling index()
at runtime, this happens all the time. The real problem is:
var_vec[i].insert(888);
var_vec[i]
is a std::variant
. It does not have a method called insert()
.
std::get<1>(var_vec[i]).insert(888);
This gives you the variant's set, which will happily allow you to insert()
something.
One problem with this overall approach is that if you, for some reason, want to modify your variant, and that std::set
is no longer its 2nd alternative, for some reason, all of the above logic will break again.
You should consider using std::holds_alternative
, instead of index()
, and using a type with std::get
instead of an index, which will automatically adapt to this kind of a change.