0

Lets say I have a struct as value

struct Friend { Person * a, Person* b}

Then I have another class as key

class Relation;

Now I want to create a key value relation

std::unordere_map<Relation*, Friend> my_map;

I have tried

Relation* r; 
Person * p1;
Person * p2;
my_map[r] = {p1, p2}; // works

my_map[r] = new Friend(p1,p2); // does not work 
// error says : error: no match for 'operator='

// my_map[r] = Friend(p1, p2); /// also does not work
 // After Edit from Zan
// error: no matching function for call to 'Friend::Friend()'


struct Friend { 
     Friend(Person* x, Person* y){
     a = x;
     b = y;
     }

     Person * a;
     Person* b;
}
6
  • 2
    The value type in your map is Friend, not Friend* (ie: not a pointer). Therefore my_map[r] = new Friend(p1,p2); won't work, as you're trying to store a pointer as the value Commented Nov 18, 2016 at 16:57
  • 2
    If you really want to store a pointer as your value type, then you'll have to change your map definition, std::unordered_map<Relation*, Friend*> my_map; Commented Nov 18, 2016 at 16:59
  • @SteveLorimer Yes that did it .. I think I asked question to quick before thinking :/ Commented Nov 18, 2016 at 17:03
  • 1
    @solti you tagged this question c++11. As such, you should tend to avoid manual memory management. If you really want to store pointers, try having a look at std::unique_ptr. If you want to store a non-owning pointer, then raw pointers are fine. In c++11 and later, seeing new in your code is considered a code-smell Commented Nov 18, 2016 at 17:06
  • Also you created Relation *r but never set it to anything. It will have the value of whatever was in the stack or register before, which is bad. On some compilers and architectures trying to use that unset pointer might even crash your program (Itanium not-a-thing marking, for one). Which is much better than wondering why your program sometimes works or doesn't, depending on the values passed to some previous function. Commented Nov 18, 2016 at 17:07

3 Answers 3

2

Friend != Friend*. If you declare a std::unordered_map which has Friend as values then you can't use a Friend* and viceversa.

But I don't get what you are trying to do. It sounds like an XY problem to me. What's the purpose of Relation class? It's just to express the relationship between Person* a and b? If that's the case then the data structure is not suitable for your purpose.

By using std::unordered_map<Relation*, Friend> you are using pointers as keys but who manages the memory for Relation? Who owns it?

Maybe you just need a std::unordered_map<Person*, Person*> to store a mutual relation, or std::set<Friend> if you want to trade performance to avoid storing transitive entries.

Sign up to request clarification or add additional context in comments.

1 Comment

I had to look up what XY problem was .. and yes after knowing what it is .. this question falls in to XY problem. I was trying to simplify the complex problem but I think it ended up hurting the question (Will try to be careful next time) and yes your solution works
2

No one has really addressed the error you had. I assume your commented out error here:

// my_map[r] = Friend(p1, p2); /// also does not work
// error: no matching function for call to 'A::A()'

Is from previous code and A::A() is actually Friend::Friend(). What that error is about is that my_map[r] has to first create a default Friend value before it can do anything else. The operator[] function has to have something it can return a reference to.

If you define a default constructor that sets your Person* values to NULL or nullptr or 0 then your code will start working, except for the other problems that have been pointed out.

Don't worry about performance here. In optimization, the compiler will see that the values are written to 0 then written to the real value without ever being read and it will remove the first writes to 0.

3 Comments

thank you for the answer ... after placing default constructor A(){}; inside the struct , my_map[r] = Friend(p1, p2); works now
My another question is when you say my_map[r] has to first create a default Friend value before it can do anything else .. is there any particular reason why it need to do that.
@solti: " The operator[] function has to have something it can return a reference to."
0

Try removing new. You are trying to store a Friend* in the map rather than a Friend. If you skipped the new, it should create one one the stack then move it into the map.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.