C2582 Operator = function not available in class, when using vectors?

My program is generating the error: C2582: 'operator =' function is unavailable in 'Brick' c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility 2466
My goal is to iterate through a vector of class Objects, and iterate through a vector of Objects within each of those (so hierarchy goes class, vector, class, vector, properties I'm trying to analyze), and delete objects inside the second vector if certain parameters are true. Here is a loop I came up with to do this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void Level::RemoveLine(int line){
	for(int i = 0; i < gamePieces_.size(); i++){
		//crt new iterator per each gamepiece
		std::vector<Brick>::iterator iter = gamePieces_[i].GetPieceRectangles().begin();
		int j = 0;
		while(iter != gamePieces_[i].GetPieceRectangles().end()){
			++j;
			if(gamePieces_[i].GetPieceRectangles()[j].TestLine(line) == true){
				iter = gamePieces_[i].GetPieceRectangles().erase(iter);
			}
			else{
				++iter;
			}
		}
	}
}


The line iter = gamePieces_[i].GetPieceRectangles().erase(iter); is the line throwing the error. Aside from writing my own operator function, what can I change to fix this error?

Edit: Here is the Brick class, neglected to add it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "stdafx.h"
#include "ImageManager.h"

class Brick{
public:
	Brick(ImageManager &im);
	Brick(ImageManager &im, sf::Vector2i size, int posx, int posy, sf::Color color);
	~Brick();

	void SetSizePosTextColor(ImageManager &im, sf::Vector2i size, int posx, int posy, sf::Color color);
	void SetActiveLine();

	int GetActiveLine();
	bool TestLine(int line);

	sf::RectangleShape Brick::GetRect();

	//sfml pseudo functions
	void Move(int x, int y);
	void SetPosition(int x, int y);

	sf::Vector2f GetPosition();
	//will need to add pseudofunctions for all functions of sf::RectangleShape. R.I.P. sleep.
private:
	ImageManager &imgr;

	int line;

	sf::RectangleShape brick;
};
Last edited on
The problem is the reference on line 25. A reference cannot be reassigned. Use a pointer instead.
But in my loop, line 9, I'm only erasing the old iterator and making an instance of a new one using erase(). How is that affecting &imgr?
std::vector::erase() uses operator=() to shift elements up.
@helios Ok that makes sense now. So what options does that leave me?
> So what options does that leave me?

Perhaps the cleanest option is to wrap the reference.
std::reference_wrapper<> http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper
@JLBorges what exactly am I wrapping? The reference on line 26? The instance of the vector iterator?
1
2
3
4
5
6
7
8
9
10
11
12
class Brick{
public:

	Brick(ImageManager &im) : imgr(im) {}

	// ...

private:
	std::reference_wrapper<ImageManager> imgr ; // wrapped

	// ...
};
After doing that, imgr no longer behaves like a reference, like in this code here
1
2
3
4
5
void Brick::SetSizePosTextColor(ImageManager &im, sf::Vector2i size, int posx, int posy, sf::Color color){
//...
		brick.setTexture(imgr.tetrominoTexture);
//...
}

The error thrown is that tetrominoTexture is not a member of std::reference_wrapper<ImageManager>. imgr is an object in my ImageManager class, and I've been passing around a reference to that one object so I can use the image manager across multiple classes. So in Brick, I need the imgr to behave like a reference would. How does it do that when it is wrapped?

Edit: added std::ref(imgr) to the constructor, but now I get error C2558 no copy constructor is defined 'explicit'.
1
2
3
4
Brick::Brick(ImageManager &im, sf::Vector2i size, int posx, int posy, sf::Color color) : imgr(im){
	std::ref(imgr);
	SetSizePosTextColor(imgr, size, posx, posy, color);
}


Adding a copy constructor does not help.
1
2
3
Brick::Brick(const Brick &, ImageManager &im) : imgr(im){

}
Last edited on
I'd suggest to use a list. vector is rather slow when it comes to erase an arbitrary element.

On the other hand: why is reference so important for you? Using a pointer to ImageManager would solve that problem.
> After doing that, imgr no longer behaves like a reference, like in this code here
> void Brick::SetSizePosTextColor(ImageManager &im, sf::Vector2i size, int posx, int > posy, sf::Color color){
> //...
> brick.setTexture(imgr.tetrominoTexture);
> //...
> }

1
2
3
4
5
6
7
void Brick::SetSizePosTextColor(ImageManager &im, sf::Vector2i size, int posx, int posy, sf::Color color){
    //...
	//brick.setTexture(imgr.tetrominoTexture);
        // http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/get
        brick.setTexture(imgr.get().tetrominoTexture);
    //...
}



> So in Brick, I need the imgr to behave like a reference would. How does it do that when it is wrapped?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Brick{
public:

	Brick(ImageManager &im) : imgr_wrapper (im) {}

	// ...

private:
	std::reference_wrapper<ImageManager> imgr_wrapper ; // wrapped
        
        ImageManager& imgr() { return imgr_wrapper ; }
        const ImageManager& imgr() const { return imgr_wrapper ; }

	// ...
};


And then
1
2
3
4
5
void Brick::SetSizePosTextColor(ImageManager &im, sf::Vector2i size, int posx, int posy, sf::Color color){
    //...
        brick.setTexture( imgr().tetrominoTexture);
    //...
}



> added std::ref(imgr) to the constructor

No. Just remove it.


> Adding a copy constructor does not help.

Remove that too; use the implicitly declared copy constructor.


> I'd suggest to use a list. vector is rather slow when it comes to erase an arbitrary element.

Erasing with the remove-erase idiom on std::vector<> would be measurably faster than on std::list<>
https://en.wikipedia.org/wiki/Erase-remove_idiom
@JLBorges I added everything that you added (yes I understood it, didn't just c & p), but I still get a compiler error that repeats three times:
1
2
3
 Error	2	error C2558: class 'Brick' : no copy constructor available or copy constructor is declared 'explicit'	c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0	606
Error	15	error C2558: class 'Brick' : no copy constructor available or copy constructor is declared 'explicit'	c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0	606
Error	26	error C2558: class 'Brick' : no copy constructor available or copy constructor is declared 'explicit'	c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0	606


I'm not sure what to do, as there's no copy constructor to make explicit.
Last edited on
std::reference_wrapper<> is CopyAssignable; it would not make Brick non-copyable.

Code for testing the behaviour of the Microsoft Compiler:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <functional>

struct ImageManager {};

class Brick{
public:

	Brick(ImageManager &im) : imgr_wrapper (im) {}
    
    

	// ...

private:
	std::reference_wrapper<ImageManager> imgr_wrapper ; // wrapped

    ImageManager& imgr() { return imgr_wrapper ; }
    const ImageManager& imgr() const { return imgr_wrapper ; }

	// ...
};

int main()
{
    std::cout << "Microsoft compiler version: " << _MSC_VER << '\n' ;
    ImageManager i ;
    Brick b(i) ;
    Brick b2(b) ;
}

http://rextester.com/BTKW2870

However, the version of the C++ compiler tested is 18.00 (Visual Studio 2013).
You appear to be using an earlier version of the compiler ( 17.00 / VS 2012 ? ).

I do not have access to that particular version of the compiler; so I can only suggest an untested work-around:
try writing a copy constructor for Brick; something like this:

1
2
Brick::Brick( const Brick& that ) 
    : imgr_wrapper( that.imgr_wrapper.get() ) /* copy initialise other members */ {}
I bit the bullet and declared imgr as a pointer instead of a reference. I'm sure I could've made std::reference_wrapper work, but it did seem a bit overkill
I bit the bullet and declared imgr as a pointer instead of a reference.
Wonder why you consider this a problem?
Topic archived. No new replies allowed.