occur no matching function for call to error in c++ - c++

I'm a novice in c++, i know there is a lot of similar questions but unfortunately didn't help me to solve this problem (which is a conceptual misunderstood i think)
So i have this constructor
Field::Field(const Position &posG, const Position &posC) {
//...
}
And i am creating a Field as follows
// Create positions
Position posG, posC;
posG.x = 3;
posG.y = 3;
posC.x = 4;
posC.y = 4;
// Create pointers to positions
const Position *pPosC(&posC);
const Position *pPosG(&posG);
// Create field
Field field (pPosG, pPosC);
Where position is
struct Position {
int x;
int y;
};
Then i am getting this exception:
main.cpp:27:30: error: no matching function for call to ‘Field::Field(const Position*&, const Position*&)’
Field Field (pPosG, pPosC);
In file included from main.cpp:2:0:
Any help? Regards

Field(const Position &posG, const Position &posC);
^^^^^ ^^^^^^
Those are references. So when you try to pass pointers
Field field (pPosG, pPosC);
^^^^^ ^^^^
pointer pointer
It can't compile.
Either make the constructor accept reference pointers (const Position *&posG) or pass the value of the pointers (*pPosG), or just pass the values directly (posG).

When you have a constructor defined as
Field(const Position &posG, const Posicion &posC);
You can use objects of type Position as arguments to it, not pointers to Position.
You can use:
Field field(posG, posC);
or
Field field(*pPosG, *pPosC);

Your constructor expects references, not pointers.
As a sidenote, it's not clear why you use references or pointers.

you must define a constructor, then use of const Position *pPosC(&posC); expression.
you must define constructor-copy like this :
struct Posicion {
public :
Position(const Position &pos) // constructor copy
{
// some code here
x = pos.x;
y = pos.y;
}
int x;
int y;
};

Related

Can't delete element from vector, attempting to reference deleted function

I am making my "version" of Space Invaders in C++ using SFML library but I have a problem when I try to delete an invader.
I have this error in my code:
Enemy &Enemy::operator =(const Enemy &)': attempting to reference a deleted function
I tried to check other solutions that were recommended in this forum but I either didn't understand them or it was a different case.
EnemyControler.cpp
EnemyControler::EnemyControler()
{
Enemy::Type types[] = {
Enemy::Type::Squid, Enemy::Type::Crab, Enemy::Type::Crab,
Enemy::Type::Octopus, Enemy::Type::Octopus
};
for (int y = 0; y < 5; y++) { // Add enemies to the vector
for (int x = 0; x < 11; x++){
float enemyX = x * 40 + (gapBetweenEnemies * x * 3) + Enemy::enemyWidth; // Make horizontal gap between them
float enemyY = y * 40 + (gapBetweenEnemies * y) + Enemy::enemyHeight; // Make vertical gap between them
enemies.emplace_back(sf::Vector2f{ enemyX, enemyY }, types[y]); // Add them to the vector
}
}
}
void EnemyControler::destroyEnemy()
{
for (auto iterator = begin(enemies); iterator != end(enemies);) {
auto& enemy = *iterator;
if (enemy.isAlive()) {
iterator++;
}
else {
iterator = enemies.erase(iterator);
}
}
}
Problem is in destroyEnemy function. Specifically in iterator = enemies.erase(iterator);
EnemyControler.h
class EnemyControler
{
public:
EnemyControler();
void destroyEnemy();
private:
const int gapBetweenEnemies = 10;
std::vector<Enemy> enemies;
};
Enemy.cpp
Enemy::Enemy(sf::Vector2f startingPosition, Type type) :
Collidable(enemyWidth, enemyHeight), newPosition(startingPosition), enemyType(type), startingPosition(startingPosition)
{
}
Enemy.h
class Enemy : public Collidable
{
public:
enum class Type // enum for different looking enemies
{
Crab, Octopus, Squid
};
Enemy(sf::Vector2f startingPosition, Type type);
constexpr static float enemyWidth = 30.0f;
constexpr static float enemyHeight = 30.0f;
private:
sf::Vector2f newPosition;
Type enemyType;
const sf::Vector2f startingPosition;
};
Collidable.cpp
Collidable::Collidable(float width, float height) :
spriteSize(width, height)
{
}
Collidable.h
class Collidable
{
public:
Collidable(float width, float height);
private:
sf::Vector2f spriteSize;
};
If there isn't an easy way of fixing this problem or this problem could be fixed only by rewriting all code maybe you could suggest another way of deleting invader from the vector.
If a class has a const member variable, then the copy assignment operator for that class operator= is default-deleted by the compiler.
From https://en.cppreference.com/w/cpp/language/copy_assignment :
A defaulted copy assignment operator for class T is defined as deleted if any of the following is true:
- T has a non-static data member of non-class type (or array thereof) that is const;
This is because the compiler can't guess what it means to copy assign object A into object B, if objects of their class contain a const member variable. Should the compiler just ignore that particular member variable? Should the compiler guess that you mean it to be const, except when copy assigning, then it's okay just this once - I'll look the other way? The compiler has no idea what you would prefer, so it just deletes it.
One option is to explicitly define a copy assignment operator for your class.
However, startingPosition is already declared private, so there's little chance of anything outside of the class inadvertently changing it. I recommend just removing the const specifier.
Why does the copy assignment operator matter? I'm trying to delete things, not copy assign them
When an element is erased from a vector, all elements in the vector "above" the erased element need to be moved down to fill the gap. This happens via the copy assignment operator.
From https://en.cppreference.com/w/cpp/container/vector/erase :
Complexity
Linear: the number of calls to the destructor of T is the same as the number of elements erased, the assignment operator of T is called the number of times equal to the number of elements in the vector after the erased elements

C++ Class initialized

C++ and Class
I have a class called “Sprite”, when this is initialized it takes a bool variable:
// constructor
Sprite::Sprite(bool type)
{
// set stuff
}
// two Sprites of different types
Sprite Hero(1)
Sprite Enemy(0)
Q. How do I initialize an array of 100 Sprites of type 0?
Sprite Enemies[100] ?
My suggestion is that you use a std::vector, and then use the constructor taking a value argument.
Like
std::vector<Sprite> Enemies(100, Sprite(false));
You might need proper copy-constructor and copy-assignment operators defined for Sprite for it to work.
If you don't have vectors (or std::array which might be better in your case), then you have to declare the array as a normal array, and then use a loop to initialize each entry:
Sprite Enemies[100];
for (size_t i = 0; i < 100; ++i)
Enemies[i].set(false);
You can use a default constructor, that will simply default to the 0 value like this:
//default constructor
Sprite::Sprite()
{
//set to false
}
Sprite::Sprite(bool type)
{
// set to type
}
Now
Sprite Enemies[100]
will work
Or with a little less code use a default value in the constructor like so:
Sprite::Sprite(bool type=false)
{
//set to type
{
Unless I'm wrong, you cannot directly use constructor with parameters for object arrays. One solution is using a std::vector :
std::vector<Sprite> Ennemies(100, Sprite(false));
std::vector<Sprite> Ennemies(100, {false}); // C++11 style
If you really want C-style array, you can get it, by an example :
Sprite* pEnnemies = &Ennemies.front();
One other solution is using the new C++11 container std::array which is only a C-Style array in STL syntax :
std::array<Sprite, 100> Ennemies(Sprite(false));
When creating an array of classes, they must be created by the default constructor.
You could add a default value "= false" for your type parameter, and then the code would work. It's not very flexible though, as you might want an array of the other type.
Another way is to allow your sprite to be reset after construction with a different type. After creating your array of blank sprites, call reset(type) on them in a for loop.
If you really need to use a non-default constructor on your elements, use std::vector. There are two ways to do it.
std::vector<Sprite> Enemies;
Enemies.reserve(100);
for (int i = 0; i < 100; i++)
{
Enemies.push_back(Sprite(0));
}
or
std::vector<Sprite> Enemies(100, Sprite(0));
For the sake of completeness, there is one last method using placement-new:
unsigned char data[sizeof(Sprite) * 100];
Sprite* ptr = reinterpret_cast<Sprite*>(&data[0]);
Sprite* end = ptr + 100;
for (; ptr != end; ++ptr)
new (ptr) Sprite(0);
This is pretty much what the other answers, that don't rely on the copy-constructor use internally.
If Sprite has a non-trivial destructor you will have to call it explicitly using another loop at the end of data's lifetime:
Sprite* ptr = reinterpret_cast<Sprite*>(&data[0]);
Sprite* end = ptr + 100;
for (; ptr != end; ++ptr)
ptr->~Sprite();
Many thanks all for taking a look, after reading comments I've found this works, overloading the constructor:
class Sprite
{
public:
Sprite();
Sprite(bool type);
void Move();
private:
unsigned int x, y, Ammo;
bool Alive;
bool Type;
};
// constructor
Sprite::Sprite()
{
Alive = true;
Type = 0;
Ammo = 25;
x = random(0, 82);
y = random(0, 20);
}
Sprite::Sprite(bool type)
{
Alive = true;
Type = 1;
Ammo = 25;
x = 20; // get x from btn press
y = 10; // get y from btn press
}
Sprite Hero(1);
Sprite Enemies[100];
Use a default argument:
Sprite::Sprite(bool type=false) : mymember(type)
{}
and then when you declare:
Sprite Enemies[100];
it will call the default ctor for all 100 elements.
You should learn about member-initializer lists, the proper way to write a constructor in C++ is:
Sprite(bool type=false); // declaration
...
Sprite::Sprite(bool type) : // definition
x(random(0, 82)),
y(random(0, 20)),
Ammo(25),
Alive(true),
Type(type)
{}

Operator overload = and const reference

I'm trying to construct a class for colors in C++,
this is not an homework is just that I'm still struggling with references and const.
--Color.h
class Color{
private:
double r;
double g;
double b;
double a;
public:
//constructor, getters and setters...
Color& operator =(Color& other_color); //(1)
}
--Color.cpp
Color& operator=(Color& other_color){
this->r = other_color.get_r(); //line 41
this->b = other_color.get_b();
//and so on...
return *this;
}
like this it works fine but I heard one has to put a const to avoid that by fault the object will be modified by the assignement operation, so one has to declare the other object as const. Like this:
Color& operator =(Color const& other_color); //(2)
but it gives me this errors:
/Users/../color.cpp:41: error: passing 'const Color' as 'this' argument of 'float Color::get_r()' discards qualifiers
so here is my question...
what is happening here? second what would happen if I don't declare other_color as const? what are the possible errors?
PS.: little bonus question:
I want to pass my variable to the opengl glColor4v(colorx.return_rgba()) returning the array [r,g,b,a] of the class Color. This:
float* Color::return_rgba(){
float rgba[4] = {this->r, this->g, this->b, this->a};
return rgba;
}
won't work because rgba won't be in scope anymore after the return so it will be deleted and my pointer will point to not initialized adresses, damn...
passing 'const Color' as 'this' argument of 'float Color::get_r()' discards qualifiers
This means you have to take it further. get_r is probably declared as
float get_r()
and to make it work (const-correctly), you should make it
float get_r() const
second what would happen if I don't declare other_color as const?
You would be unable to assign from const-qualified Colors. You usually want to be able to use const objects, among other as source of assignment. Moreover, it makes the intent not to modify the source clear to the reader of the code.
I want to pass my variable to the opengl glColor4v(colorx.return_rgba()) returning the array [r,g,b,a] of the class Color.
Return a special "vehicle" that would contain the array and convert automatically to float*. Something along
struct ColorQuadruplet
{
float data_[4];
// add initialization and such here
operator float*() { return data_; }
};
ColorQuadruplet Color::get_rgba() const
{
ColorQuadruplet ret;
// fill ret
return ret;
}
You have two choices here. One is for your operator= to directly access to the members of the source object:
Color &operator=(Color const &other) {
r = other.r;
g = other.g;
b = other.b;
a = other.a;
}
The other (which you probably want to do in any case, if you insist on having accessors for the color components at all) is to const-qualify the accessors you've written:
double get_r() const { return r; }
^^^^^
The const here is the part I've added that you apparently don't have.
Edit: as far as passing the values to glColor goes, I'd consider a small front-end something like this:
gl_color(Color const &c) {
glColor4d(c.r, c.g, c.b, c.a);
}

C++ pass by pointer

Guys, I am very new to c++. I have just wrote this class:
class planet
{
public:
float angularSpeed;
float angle;
};
Here is a function trying to modify the angle of the object:
void foo(planet* p)
{
p->angle = p->angle + p->angularSpeed;
}
planet* bar = new planet();
bar->angularSpeed = 1;
bar->angle = 2;
foo(bar);
It seem that the angle in bar didn't change at all.
Note that you are passing bar by pointer, not by reference. Pass-by-reference would look like this:
void foo(planet& p) // note: & instead of *
{
p.angle += p.angularSpeed; // note: . instead of ->
}
Pass-by-reference has the added benefit that p cannot be a null reference. Therefore, your function can no longer cause any null dereferencing error.
Second, and that's a detail, if your planet contains only public member variables, you could just as well declare it struct (where the default accessibility is public).
PS: As far as I can see it, your code should work; at least the parts you showed us.
Appearances must be deceptive because the code should result in foo(bar) changing the contents of the angle field.
btw this is not passing by reference, this is passing by pointer. Could you change the title?
Passing by reference (better) would be
void foo(planet& p) {
p.angle += p.angularSpeed;
}
planet bar;
bar.angularSpeed=1;
bar.angle=2;
foo(bar);
You might also consider a constructor for planet that takes as parameters the initial values of angle and angularSpeed, and define a default constructor that sets them both to 0. Otherwise you have a bug farm in the making due to unset values in planet instances.

C++ types and functions

I'm having some trouble compiling my code - it has to do with the types I'm passing in. Here is what the compiler says:
R3Mesh.cpp: In copy constructor 'R3Mesh::R3Mesh(const R3Mesh&)':
R3Mesh.cpp:79: error: no matching function for call to 'R3Mesh::CreateHalfEdge(R3MeshVertex*&, R3MeshFace*&, R3MeshHalfEdge*&, R3MeshHalfEdge*&)'
R3Mesh.h:178: note: candidates are: R3MeshHalfEdge* R3Mesh::CreateHalfEdge(const R3MeshVertex*&, const R3MeshFace*&, const R3MeshHalfEdge*&, const R3MeshHalfEdge*&)
R3Mesh.cpp: In constructor 'R3MeshHalfEdge::R3MeshHalfEdge(const R3MeshVertex*&, const R3MeshFace*&, const R3MeshHalfEdge*&, const R3MeshHalfEdge*&)':
R3Mesh.cpp:1477: error: invalid conversion from 'const R3MeshVertex*' to 'R3MeshVertex*'
R3Mesh.cpp:1477: error: invalid conversion from 'const R3MeshFace*' to 'R3MeshFace*'
R3Mesh.cpp:1477: error: invalid conversion from 'const R3MeshHalfEdge*' to 'R3MeshHalfEdge*'
R3Mesh.cpp:1477: error: invalid conversion from 'const R3MeshHalfEdge*' to 'R3MeshHalfEdge*'
Here is how I define my R3MeshHalfEdge:
struct R3MeshHalfEdge {
// Constructors
R3MeshHalfEdge(void);
R3MeshHalfEdge(const R3MeshHalfEdge& half_edge);
R3MeshHalfEdge(const R3MeshVertex*& vertex, const R3MeshFace*& face,
const R3MeshHalfEdge*& opposite, const R3MeshHalfEdge*& next);
R3MeshVertex *vertex;
R3MeshFace *face;
R3MeshHalfEdge *opposite;
R3MeshHalfEdge *next;
int id;
};
This is what the first error complains about:
R3MeshHalfEdge *R3Mesh::
CreateHalfEdge(const R3MeshVertex*& vertex, const R3MeshFace*& face,
const R3MeshHalfEdge*& opposite, const R3MeshHalfEdge*& next)
{
// Create half_edge
R3MeshHalfEdge *half_edge = new R3MeshHalfEdge(vertex, face, opposite, next);
// Set half_edge ID
half_edge->id = half_edges.size();
// Add to list
half_edges.push_back(half_edge);
// Return half_edge
return half_edge;
}
This is what the second error complains about:
R3MeshHalfEdge::
R3MeshHalfEdge(const R3MeshVertex*& vertex, const R3MeshFace*& face,
const R3MeshHalfEdge*& opposite, const R3MeshHalfEdge*& next)
: vertex(vertex),
face(face),
opposite(opposite),
next(next),
id(0)
{
}
Here is where I call the CreateHalfEdge function:
for(int i=0; i<mesh.NFaces(); i++)
{
R3MeshFace *f = mesh.Face(i);
vector<R3MeshVertex *> face_vertices; // assume vertices are stored in order around the perimeter of the face
for(unsigned int j = 0; j<f->vertices.size(); j++)
{
R3MeshVertex *v1 = f->vertices[j];
R3MeshVertex *v2;
if(j==f->vertices.size()-1)
v2 = f->vertices[0];
else
v2 = f->vertices[j+1];
int v1_id = v1->id;
int v2_id = v2->id;
R3MeshHalfEdge *next = NULL;
R3MeshHalfEdge *opposite = NULL;
R3MeshHalfEdge *half_edge = CreateHalfEdge(v1, f, opposite, next);
}
... }
The constructor is wrong:
R3MeshHalfEdge(const R3MeshVertex*& vertex, const R3MeshFace*& face,
const R3MeshHalfEdge*& opposite, const R3MeshHalfEdge*& next);
You pass pointers to const and assign them to pointers to non-const, which fails.
Correct it like so:
R3MeshHalfEdge(R3MeshVertex* vertex, R3MeshFace* face,
R3MeshHalfEdge* opposite, R3MeshHalfEdge* next);
As a remark:
there are two level of const with pointers: pointers to const (const X*) and const pointers (X* const) the former can point to something else but cannot change the object pointed to while the latter cannot be rebound to another object but can change the object pointed. You can combine them to have a const pointer to const (const X* const)
don't pass pointers by reference (*&) unless you intend to modify the pointer itself, and not the object pointed.
Saying const type *&parameter means that you can modify parameter:
void foo(const int *&parameter)
{
int bar= 0;
parameter= &bar;
}
I suspect you don't want to do that. Instead of passing pointers by reference, either pass them by value (since you aren't modifying them) or pass them by const reference (const type * const &parameter).
You're passing non-const pointers to a function that expects const pointer arguments, it seems.
Note:
...But this shouldn't be a problem. I suspect there's something else going on here, but the question is missing some information. The compiler error is about something in the copy constructor R3Mesh::R3Mesh(const R3Mesh&), which isn't shown in the question.
Edit: OK, it is shown now. I would suggest clearing up the const reference to pointer issues first, and seeing what's left.
The second error is pretty clear, actually - either the arguments to the R3MeshHalfEdge constructor shouldn't be references to const pointers (which tell the compiler you don't intend to change the objects they point to) or the data members you assign those arguments to should be const pointers themselves.
You need to look at your argument and reevaluate what should be constant and what shouldn't.
Your compiler error is thrown because you are pointing a nonconstant pointer (vertex, for example) at constant memory (the vertex argument). In C++ constant and nonconstant variables are different types.
Read through this for a lot more detail.
If you just want it to work, remove all your consts and it will compile. If you want your arguments to be constant, you'll have to do copy copying and assignments of data (not pointers!) to remove the error.
Also, rename your arguments so that you don't have name collisions with your member variables.