zenna
zenna

Reputation: 9176

Can't insert element into nested stl set of ints

I have a nested set of ints but I cannot insert elements into the nested sets.

std::set<std::set<int> > centre_as_set = bitset_to_set(centre->second->bit_partitions);
std::set<std::set<int> >::iterator set_itr;
for ( set_itr = centre_as_set.begin(); set_itr != centre_as_set.end(); ++set_itr ) {
    set_itr->insert(4);
    std::set<int>::iterator node_itr;
    for ( node_itr = set_itr->begin(); node_itr != set_itr->end(); ++node_itr ) {
            std::cout << *node_itr;
        }
    }
}

The error is

Partition_standalone.cpp:612: error: passing ‘const std::set, std::allocator >’ as ‘this’ argument of ‘std::pair, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(const _Key&) [with _Key = int, _Compare = std::less, _Alloc = std::allocator]’ discards qualifiers

I can't quite decipher that template error, any help appreciated.

Upvotes: 2

Views: 1619

Answers (2)

Markus Kull
Markus Kull

Reputation: 1479

Edit: This answer is wrong as per the comment of georg.

I dont have a compiler here, but the full declaration of std::set is:

template < class Key, class Compare = less<Key>,
           class Allocator = allocator<Key> > class set;

The "Key" of the outermost set is "std::set". The Comparator is "std::less>", or short "operator<(set, set)" which is undefined. The compiler warns about this only on the first use/instantiation of the comparator.

I dont think there is a useful ordering/comparator for std::set's. You are better off using std::vector which doesnt order the elements and doesnt need a comparator.

Oh, and it is not allowed to change (at runtime) the set keys if this would affect the ordering. But that would be a runtime error, not a compile error.

Upvotes: 0

Georg Fritzsche
Georg Fritzsche

Reputation: 98984

The elements in a set are not mutable and you are trying to use the non-const member function insert() on a const instance of std::set<int>. There is the following nice comment if you follow the iterator symbol to its declaration in stl_set.h:

// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 103. set::iterator is required to be modifiable,
// but this allows modification of keys.
typedef typename _Rep_type::const_iterator iterator;

C++98 and C++03 allowed modification, but this is a defect and already fixed in non-ancient GCC versions and VC10. The mentioned defect report can be found here and will be incorporated into the next standard.

Use e.g. something like the following instead to add the value 4:

// Readability:
typedef std::set<int> IntSet;
typedef std::set<IntSet> IntSetSet;

// Helper:
IntSetSet add_value_to_sets(const IntSetSet& in, int i) {
    IntSetSet ss;
    IntSetSet::iterator set_itr;
    for ( set_itr = in.begin(); set_itr != in.end(); ++set_itr ) {
        IntSet s = *set_itr;
        s.insert(4);
        ss.insert(s);
    }
    return ss;
}

// ...
IntSetSet centre_as_set = 
    add_value_to_sets(bitset_to_set(centre->second->bit_partitions), 4);

Upvotes: 5

Related Questions