0

I am learning to code in c++ and I am learning to use sets currently, with the code (I will not use the specific code because of the length but will use an example) it wants me to use a struct and a set and with the things that needs to be done I need to be able to ​access and edit a variable in said struct while iterating through the set.

Here is an example of what I am trying to do:

#include <iostream>
#include <set>

using namespace std;

struct myStruct
{
    int testVal;
    int exVal;
};

int main()
{
    set<myStruct> tst;
    myStruct struc;
    
    struc.testVal = 10;
    struc.exVal = 5;

    tst.insert(struc);
    
    struc.testVal = 1;
    struc.exVal = 7;
    
    tst.insert(struc);
    
    for (set<myStruct>::iterator it = tst.begin(); it != test.end(); it++)
    {
        if (*it.testVal >= *it.exVal)
        {
            //do something
        }
    }
    
    return 0;
}

but whenever I try to do something like this it always gives me a lot of errors. (This is an example so what is trying to be done may seem like a pointless reason to try to do this) One of the main errors is 'std::set<[struct name]>::iterator {aka struct std::_Rb_tree_const_iterator<[struct name]>' has no member named '[struct value name]'

(anything in square brackets is not part of the error but dependent on what is in the code)

in the case of this example I put here the error would say:

error: 'std::set<myStruct>::iterator {aka struct std::_Rb_tree_const_iterator<myStruct>' has no member named 'testVal'

So how do I extract a value from a struct inside of a set using an iterator, and even possibly change it?

Shadow
  • 25
  • 3
  • 2
    For a set, your struct needs to be comparable. Try to find examples otline. – Ulrich Eckhardt Dec 03 '21 at 17:24
  • Since you are still learning, it's important to be able to _read and understand_ the first error reported. In this code, you should be getting an error from the line `struc.exVal = 5` about a missing semicolon. Does that make sense? Can you fix that? – Drew Dormann Dec 03 '21 at 17:26
  • Off-topic: About [`using namespace std`](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice)... – Aconcagua Dec 03 '21 at 17:29
  • For your first error, `*it.testVal` is parsed as `*(it.testVal)`, and the iterator itself doesn't have a member called `testVal`. To fix it, `(*it).testVal` or `it->testVal`. – Artyer Dec 03 '21 at 17:34
  • @DrewDormann I meant to put the semicolon in the example I just forgot. – Shadow Dec 03 '21 at 17:34
  • @Artyer Thank you! that fixed it. – Shadow Dec 03 '21 at 17:38

1 Answers1

3

std::set ensures it's elements are unique by having them in order. By default, that uses <. You don't have a < for myStruct, nor do you make a set with a different order.

The simplest fix would be to add

bool operator< (const myStruct & lhs, const myStruct & rhs) {
    return std::tie(lhs.testVal, lhs.exVal) < std::tie(rhs.testVal, rhs.exVal);
}

You may have to #include <tuple> for that.

even possibly change it?

You can't modify elements of a set, because that might change the order. To change it you have to take it out of the set, and put the new value in.

auto node = tst.extract(it);
// modify node.value()
tst.insert(node);
Caleth
  • 52,200
  • 2
  • 44
  • 75
  • This would be helpful if I knew what tuple was, the thing hasn't taught me about tuples yet, but the second part is very helpful, thank you. – Shadow Dec 03 '21 at 17:33
  • @Shadow `std::tie` is from ``. It creates a tuple of references from it's arguments. the `<` for tuples is a lexicographic ordering of the elements – Caleth Dec 03 '21 at 20:37