2

I have:

std::unordered_set<ui::Button*> _buttons;
std::unordered_set<Sprite*> _sprites; 
std::unordered_set<Sprite*> _someOtherSprites; 

Both ui::Button and Sprite, inherit from Node.

So for example, I can do:

for(Node* node : _sprites){
    node->setPosition(1,2); 
}

for(Node* node : _someOtherSprites){
    node->setPosition(1,2); 
}

for(Node* node : _buttons){
    node->setPosition(1,2);
}

Since I need to do the same operations on both sets, is there some way do this with just one set of loops ? I mean keeping all the code that executes within the loops in one place, instead of repeating it in different loops like above ?

I have to maintain sprites,someOtherSprites and buttons in separate sets.

Can I do something like this:

std::unordered_set<std::unordered_set<Node*>> mySets;
mySets.insert(_buttons); 
mySets.insert(_sprites);
mySets.insert(_someOtherSprites);

for(auto mySet : mySets)
    for(Node* node : mySet){
        node->setPosition(1,2);
    }
}

I have no necessity to do this. I am just curious if something like this is possible.

Rahul Iyer
  • 19,924
  • 21
  • 96
  • 190
  • Perhaps [see here](https://stackoverflow.com/questions/30687305/c-equivalent-of-using-t-extends-class-for-a-java-parameter-return-type) for one possible solution. But in general, if you need to maintain separate collections, then why not just continue doing that? – Tim Biegeleisen Apr 19 '19 at 04:28
  • @TimBiegeleisen I was just curious if something like this is possible. There is no necessity. – Rahul Iyer Apr 19 '19 at 04:28
  • 1
    If you are keeping each subtype in its own set, can you store them *by value* rather than using pointers to the *free store* (heap)? – Galik Apr 19 '19 at 04:39
  • @Galik - I have no choice - The pointers are created by the game engine we use. You can create a sprite via a helper method that returns a pointer. I think the reason they intend you to use a pointer and not a value, is because you are manipulating a specific sprite on screen. It doesn't make sense to use a value. – Rahul Iyer Apr 19 '19 at 06:58

1 Answers1

1

A better option is to use a list or vector of unordered_set pointers, then push pointers to the sets you want to modify. Since the types stored in your unordered sets are different, but share a common base, you need to assemble those into a container with the common base before you can operator on all of them.

std::vector<Node *> myObjects;
// optional myObjects.reserve(_buttons.size() + _spriites.size() + ...)
for (Node *n: _buttons) myObjects.push_back(n);
for (Node *n: _sprites) myObjects.push_back(n);

Then just make a pass thru myObjects calling your function on each node.

Or you can define a lambda to use in your loops.

auto fn = [](Node *n) { n->setPosition(1, 2); }

for (Node *node: _sprites) {
    fn(node);
}
for (Node *node: _buttons) {
    fn(node);
}
1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
  • This looks like what I am looking for! Correct me if I'm wrong but since you are using &, the entire contents of _buttons and _sprites is not copied! We are just using a reference, correct ? – Rahul Iyer Apr 19 '19 at 04:31
  • @KaizerSozay It uses a pointer, not a reference. The contents are not copied. – 1201ProgramAlarm Apr 19 '19 at 04:37
  • I thought & was a reference. – Rahul Iyer Apr 19 '19 at 04:38
  • @KaizerSozay Maybe this should explain for you: https://stackoverflow.com/questions/6877052/use-of-the-operator-in-c-function-signatures – Amadeus Apr 19 '19 at 04:40
  • This doesn't seem to work - I can put an std::unordered_set in the vector. But I cannot put an std::unordered_set in it. The error is 1. Candidate function not viable: no known conversion from 'unordered_set, equal_to, allocator>' to 'const unordered_set, equal_to, allocator>' for 1st argument – Rahul Iyer Apr 19 '19 at 07:19
  • I guess it has to do with the hash function used by Sprite and Node, but its way beyond me. – Rahul Iyer Apr 19 '19 at 07:20
  • It won't work even if I try to use std::vector> foo; to hold each set. Similar error: 1. Candidate function not viable: no known conversion from 'unordered_set, equal_to, allocator>' to 'const unordered_set, equal_to, allocator>' for 1st argument – Rahul Iyer Apr 19 '19 at 07:22
  • You have a list of `std::unordered_set` and you want to push a `std::unordered_set*` into that. Huh? – Passer By Apr 19 '19 at 08:57
  • @KaizerSozay I focused on your for loops and missed the unordered sets storing different pointer types. I've altered my answer to handle that. – 1201ProgramAlarm Apr 19 '19 at 14:20
  • @PasserBy I focused on the for loops and missed the unordered sets storing different pointer types. I've edited the answer to handle that. – 1201ProgramAlarm Apr 19 '19 at 14:20
  • Perhaps I wasn't clear - obviously we can take each individual Node* out of each of the sets and put them in a common set and iterate. But I'm looking for a way to just use the unordered_set's, since each is an unordered_set of some derived node from the same base node. I guess it isn't possible since the unordered_set and the thing it contains is considered a different type. – Rahul Iyer Apr 20 '19 at 01:57