2

In this template function, I am trying to retrieve at element from a boost ptr_map. I have omitted error handling code for clarity.

template <typename K, class T>
class A
{
public:
    void TryGet(const K &key, T &o) { o = mObjects.at(key); }
private:
    boost::ptr_map<K, T> mObjects;
};

typedef A<std::string, B> myClass;

I get the compiler error C2582: 'operator =' function is unavailable in 'B'. Why does the assignment of the return value of mObjects.at() to a reference need access to an assignment operator of the instantiated class? What is the correct way to return this value?

Drew S.
  • 23
  • 3

4 Answers4

3

Why does the assignment of the return value of mObjects.at() to a reference need access to an assignment operator of the instantiated class?

When you are assigning to a reference, you are assigning to the object that the reference references.

int i = 0;
int& iRef = i;   // There is no assignment, just initializing the reference.
iRef = 10;       // Same as i = 10

Update, in response to OP's comment

What you are seeing is the equivalent of:

int j = 10;
int& jRef = j;
iRef = jRef;     // Same as i = j
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • I dont see how this is equivalent. The mObjects.at(...) returns a reference to an object. So I would have thought the line o = mObjects.at(...) is closer to your int &ref = i (i.e. no assignment) – Drew S. Apr 22 '16 at 15:25
2

I think that you're asking "why can't I re-target a reference"?

What I mean by that is that you create a reference (let's call it ref1) that references a variable a (int& ref1 = a;) and then if you have another reference (ref2) that references a variable b (int& ref2 = b;`), you want to know why:

ref1 = ref2; 

doesn't change ref1 to reference b, instead of doing a = b.

Is that correct? If so, the answer is that "that's not now references work in C++". They can only be initialized once, and after that they cannot be changed.

Here's a discussion of this topic: Why are references not reseatable in C++

Community
  • 1
  • 1
Marshall Clow
  • 15,972
  • 2
  • 29
  • 45
1

Now I get it. You don't know how references work in C++. Maybe your familiarity with Java is throwing you off track. In C++, references are simple aliases -- so you are attempting to assign directly to the object in question (which you have indicated is not legal). In Java, "references" are roughly the equivalent of C++ smart pointers. By wrapping your unnasignable types in those, you might be able to make this approach work.

boost::ptr_map<K, shared_ptr<T> > mObjects;

void TryGet(const K &key, shared_ptr<T> & o )
   {
   o = mObjects.at(key);
   }
Community
  • 1
  • 1
Brent Bradburn
  • 51,587
  • 17
  • 154
  • 173
  • note: OP code wouldn't work in java either, since the object reference was passed by value (i.e. `o = bla` won't change the argument in the caller) – M.M Apr 23 '16 at 12:50
  • @M.M: Good point. That's one of the nice things about C++ -- it's easy to remember how parameters are passed because pass-by-reference and pass-by-pointer have an explicit syntax. Java, and others, have subtle rules about how parameters are passed (and assigned). I was just making a guess that the OP was thinking in terms of Java, based on the different way that Java uses the term "reference". – Brent Bradburn Apr 23 '16 at 16:40
0

The problem of your code is

boost::ptr_map<K, T> mObjects;

boost::ptr_map need tow classes with overloaded assignment operator. You must overload assignment operator in Type B, if you want to use boost::ptr_map

erfan zangeneh
  • 334
  • 1
  • 2
  • 10