4

im using simple vector push_back to object of Type A and getting this error , this is my code :

class A 
{
    public:
    A(int a,int b,int c);
};


#include "A.h"
....
....
....
....
std::vector<A>* vec_objects = new std::vector<A>();

while(....some condition ...) 
{

    A a(1,2,3)
    vec_objects->push_back(a);
}

getting this error:

c:\program files\microsoft visual studio 9.0\vc\include\xutility(3159) : error C2582: 'operator =' function is unavailable in 'A'
1>        c:\program files\microsoft visual studio 9.0\vc\include\xutility(3187) : see reference to function template instantiation 'void std::_Fill<A*,_Ty>(_FwdIt,_FwdIt,const _Ty &)' being compiled
1>        with
1>        [
1>            _Ty=A,
1>            _FwdIt=A *
1>        ]
1>        c:\program files\microsoft visual studio 9.0\vc\include\vector(1231) : see reference to function template instantiation 'void std::fill<A*,_Ty>(_FwdIt,_FwdIt,const _Ty &)' being compiled
1>        with
1>        [
1>            _Ty=A,
1>            _FwdIt=A *
1>        ]
1>        c:\program files\microsoft visual studio 9.0\vc\include\vector(1153) : while compiling class template member function 'void std::vector<_Ty>::_Insert_n(std::_Vector_const_iterator<_Ty,_Alloc>,unsigned int,const _Ty &)'
1>        with
1>        [
1>            _Ty=A,
1>            _Alloc=std::allocator<A>
1>        ]
1>       

what i did wrong ?

user63898
  • 29,839
  • 85
  • 272
  • 514
  • Are the member variables of `A` const? – hmjd Jul 03 '12 at 10:57
  • its compilation , if i remove the vec_objects->push_back(a); its working fine – user63898 Jul 03 '12 at 11:03
  • 1
    @user63898: The code you've posted compiles, once I fix the obvious syntax errors: http://ideone.com/jeMXm. Perhaps you could post a minimal complete example that reproduces the error; without that, we can only guess at the problem – Mike Seymour Jul 03 '12 at 11:20
  • Especially post the definition of class A (definition = all member declarations, i.e. what goes in header; method bodies are not needed), because the problem is that it does not fulfil requirements of `push_back` and we can't tell why when you don't show the definition. – Jan Hudec Jul 03 '12 at 13:07

3 Answers3

19

An element of vector must be:

  • Copyable, i.e., have a constructor compatible with T(const T&).
  • Assignable, i.e., have an operator= compatible with operator=(const T&).
  • Default-constructible, i.e., have a constructor compatible with T().

While the error indicates the assignable requirement is violated, the code suggests otherwise. Every class gets a compiler-generated copy constructor and assignment operator unless they are defined manually, so your class actually should be assignable. However default constructor is only generated implicitly if there are no other constructors defined. You have a constructor, therefore also have to define a default constructor.

As Mike noted, the requirements were reduced to only moveable in C++11, but you would need a compiler that already supports respective C++11 features and would have to have those features enabled. However the paths in the errors indicate Visual Studio 9.0, a.k.a Visual Studio 2008, which predates C++11, so the restriction applies.


The copyable and assignable are satisfied by default unless you broke them. The specification says,

  • In 12.8.4:

    If the class definition does not explicitly declare a copy constructor, one is declared implicitly.

  • In 12.8.10:

    If the class definition does not explicitly declare a copy assignment operator, one is declared implicitly.

In both cases it is only defined if all base classes and all members have accessible and non-ambiguous corresponding copy constructor respectively copy assignment operator.

Community
  • 1
  • 1
Jan Hudec
  • 73,652
  • 13
  • 125
  • 172
  • 2
    That was the case before 2011. These days, the requirements are considerably less strict. For `vector`, the type must be movable, and only needs to be copyable or default-constructible for operations that require those properties. – Mike Seymour Jul 03 '12 at 11:10
  • 1
    @MikeSeymour: Yes, but the error messages quoted in the question clearly come from Visual Studio 2008, which has no traces of any C++11 features (at the time they were still in state of proposal and Microsoft wasn't showing much interest in C++) – Jan Hudec Jul 03 '12 at 12:53
  • I'm sure that's clear to you, but I'm no expert in identifying supported language features from snippets of compiler output, and your answer didn't mention that it was referring to a particular historical version of the language. – Mike Seymour Jul 03 '12 at 13:05
  • 1
    @MikeSeymour: Sure. The note is relevant in general (I identified the compiler because I also have the dubious honour to work with it). – Jan Hudec Jul 03 '12 at 13:10
5

There's nothing wrong with the code you've posted. It sounds like your real class (or a base class) declares a non-public assignment operator. This means that the class is not assignable, and so there are restrictions on how it can be used in standard containers. You will also have problems if it's not copyable - that is, if a non-public copy constructor is declared.

In C++03, it can't be used at all. You will need to make it copy-constructible and assignable to use it in any standard container.

In C++11, it can be stored in a vector as long as it's movable. push_back might not work if it's also uncopyable, in which case you can use emplace_back(1,2,3) or push_back(std::move(a)).

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
1

You need to add operator= and copy-constructor to class A

class A 
{
    public:
    A(int a,int b,int c);
    A(const A& element);
    A& operator=(const A& element);     //which needs definition
};
Blood
  • 4,126
  • 3
  • 27
  • 37