tags:

views:

140

answers:

8

I am not sure why this doesn't compile:

std::vector< const Obj& > myVector;

void foo(const Obj& obj) 
{
    myVector.push_back( obj );  
}  

Sorry, a bit of additional info on what I'm trying to achieve: I can't change the signature of foo without breaking an interface, but I just want to hang onto the Objects that get passed through foo. I do want to store pointers to them, but I'm confused about the syntax of how to do that.

+4  A: 

I'm not sure if you can put references into a container like this. Use

 std::vector<const Obj *> myVector

instead as that's semantically equivalent anyway.

antti.huima
+4  A: 

You cannot use references as the types in a vector. You can use raw pointers, smart pointers (boost/std::tr1 shared_ptr) or other constructs like boost::ref and boost::cref that provide wrappers around plain references to adapt to containers.

David Rodríguez - dribeas
+4  A: 

Vectors only work with value types; you cannot have a vector of references.

Part of the reason is that references must be bound to an existing variable as they are created, and they can never be re-bound. For a vector to be able to hold 10 elements at their "default" value is impossible with a reference type:

std::vector<const T& obj>(10); // cannot work

Similarly, you cannot re-assign a value to a reference (unless your intention was to modify the value of the original variable) so suddenly myVec[0] = 7 doesn't work either.

meagar
+14  A: 

You can't have an vector of references. as the things in a vector must be copyable and assignable, and references are neither of these. You probably want a vector of pointers:

std::vector< const Obj * > myVector;

void foo( const Obj & obj )
{
   myVector.push_back( & obj );
}
anon
+1 Fast and complete answer.
AraK
+3  A: 

Alternatively you can use boost::ref to store references, but it is much like storing pointers.

 std::vector< boost::ref< Obj > > myVector;

As per your edits, if you want to store pointers, you can just write something like:

std::vector < const Obj* > myVector;
void foo(const Obj& obj)
{
   myVector.push_back(&obj);
}

If you use boost::ref or boost::cref:

std::vector < boost::cref < Obj > > myVector;
void foo(const Obj& obj)
{
   myVector.push_back(boost::cref< Obj >(obj) );
}

(probably you can ommit the last boost::cref in the body too, but I don't have now a compiler at hand).

Diego Sevilla
+1  A: 

You cannot store references in an STL container because references are not copy constructable. TR1 contains a reference wrapper if you really need to "simulate" storing references. Storing smart pointers (e.g. tr1::shared_ptr) or object instances is usually better.

Barry Wark
+1  A: 

Aside from problems with references being the target type for a container, you can't have const objects as the target type for a container because the type of objects that a container is instantiated with must be "Assignable" as well as "CopyConstructable" (23.1 Container requirements). Const objects aren't assignable.

To be assignable, after a 't = u operation, t must be equivalent to u where t is of type T - the type the container was instantiated with.

However, as mentioned in other answers, you can put pointers to const objects in containers.

Michael Burr
+2  A: 

The C++ Standard in chapater 23.1 Container requirements specifies:

3 The type of objects stored in these components must meet the requirements of CopyConstructible types (20.1.3), and the additional requirements of Assignable types.

In other words, a type T is usable with standard C++ containers as value type as long as it defines copy constructor. The CopyConstructible concept is explain by the standard in the cited chapater but Boost manual explains clearly and shortly what means a type is CopyConstructible

Reference does not fulfil this requirement.

mloskot