How to use vector<MyObject> with ImGui::ListBox? - c++

I'm trying to display a vector of objects in a listbox that will be rendered dynamically in every frame.
This is my class and I want to display every attribute later in the listbox:
class Waypoint {
public:
int x, y, z;
char action;
};
What I'm trying now as I don't really know is this:
Waypoint wp1;
wp1.action = 'R';
wp1.x = 100;
wp1.y = 100;
wp1.z = 7;
Waypoint wp2;
wp2.action = 'S';
wp2.x = 100;
wp2.y = 100;
wp2.z = 6;
std::vector<Waypoint> listbox_items { wp1, wp2 };
static int listbox_item_current = 1;
ImGui::ListBox("listbox::Cavebot", &listbox_item_current, listbox_items);
Of course this is not working, and I'm getting this error:
E0304 no instance of overloaded function "ImGui::ListBox" matches the argument list
How can I display dynamically all my objects attributes in the listbox?

ImGui::ListBox takes a char* as a displayed text, so you could not use a single char. You should re-design your class like this:
class Waypoint {
public:
int x, y, z;
std::string action;
};
Then use this function:
bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items)
Example:
bool waypoint_getter(void* data, int index, const char** output)
{
Waypoint* waypoints = (Waypoint*)data;
Waypoint& current_waypoint = waypoints[index];
*output = current_waypoint.action.c_str(); // not very safe
return true;
}
ImGui::ListBox(
"listbox::Cavebot",
&listbox_item_current,
waypoint_getter,
listbox_items.data(),
listbox_items.size()
);

Related

default value for a pointer parameter

I'm trying to create a class for employees, and have a problem with its constructor.
My class looks like that (please note the name parameter which is char* type):
class Employee {
int id;
char * name ;
float salary;
int hours;
int extra;
public:
//constructor
Employee(int, char *, float, int, int);
//Getters and Setters:
void setId(int a) { id = a; }
int getId() { return id; }
void setName(char * c) { name = c; }
char * getName() { return name; }
void setSalary(float f) { salary = f; }
float getSalary() { return salary; }
void setHours(int h) { hours = h; }
int getHours() { return hours; }
void setExtra(int e) { extra = e; }
int getExtra() { return extra; }
};
I built a constructor and I want it to have default parameters, and I don't know how to deal with the name parameter to have a default of let's say "unknown".
This is the constructor:
Employee::Employee(int i = 123456789, char * na, float sal = 30, int ho = 45, int ex = 10)
{
id = i;
name = na;
salary = sal;
hours = ho;
extra = ex;
}
You can use a character array, and initialise the array to point to the first element of the array. You can store the array for example as a static member:
// in the class definition
inline static char default_name[] = "unknown";
// in argument list of the constructor
... char * na = default_name, ...
Although, you may want to consider whether it makes sense for name to be pointer to non-const. Perhaps a pointer to const would suffice. In such case, you could initialise it to point to the literal "unknown" directly.
A cleaner version
class Employee {
int id = 0;
char *name = nullptr;
float salary = 0.0;
int hours = 0;
int extra = 0;
And you don't need to have constructors, this depends on the case, but you get the idea that by initializing the variables on the definition you reduce the inconsistency of having multiples constructors for example

Zero-One argument Constructor

const int max_sku_length = 7;
const int max_unit_length = 10;
const int max_name_length = 75;
const double TRate = 0.13;
char m_type;
char m_sku[max_sku_length +1];
char m_unit[max_unit_length + 1];
char* m_name;
int m_Cquantity;
int m_Nquantity;
double m_price;
bool m_status;
Product()
{
this->m_sku[0] = '\0';
this->m_name = nullptr;
this->m_price = 0;
this->m_Cquantity = 0;
this->m_status = false;
this->m_Nquantity = 0;
this->m_type = '\0';
this->m_unit[0] = '\0';
}
I am new to C++. I need to create a
• Zero-One argument Constructor
This constructor optionally receives a character that identifies the product type. The default value is ‘N’. This function
stores the character receives in an instance variable
sets the current object to a safe recognizable empty state.
I constructed zero argument constructor, but I am not really sure how to do Zero-one argument constructor. Please help me out.
Use a default argument.
Product::Product (char productType = 'N') {
// your stuff
}

Returning 2D array pointer from class

I've got a class called Engine which holds and returns a buffer like so:
template <int width, int height, int meshSize>
class Engine {
public:
byte buffers[2][width][height];
byte fBuffer = 0;
byte** getBuffer() {
return buffers[fBuffer];
};
}
and I want to loop through the values in my main, but I can't seem to get it working..
byte* buff;
// main
buff = engine->getBuffer();
for (int x = 0; x < 320; x++) {
for (int y = 0; y < 320; y++) {
if (buff[x][y] != NULL) {
Serial.println(buff[x][y]);
}
// lcd.drawPixel(x, y, RGB(buff[x][y], buff[x][y], buff[x][y]));
}
}
What combination of asterisk and/or parenthesis will work?
You should return a reference to your array, rather than a pointer. I also recommend providing a const overload of getBuffer for read-only operations.
template <int width, int height, int meshSize>
class Engine {
public:
using BufferType = byte[width][height];
BufferType const& getBuffer() const {
return buffers[fBuffer];
};
BufferType& getBuffer() {
return buffers[fBuffer];
};
private:
BufferType buffers[2];
byte fBuffer = 0;
};
You can use auto to deduce this type when calling getBuffer for brevity:
auto& buff = engine->getBuffer(); // reference to the buffer

c++ initialize values static int with CLI array

So I have 2 arrays both are 2 dimensional cli::arrays.
What's the right syntax to initialize an cli::array. I tried in the example below but that doesnt work.
//Cords.h
ref class Cords {
private:
static array<int,2>^ Xcord = gcnew array<int,2>(4,4); // [4][4]
static array<int,2>^ Ycord = gcnew array<int,2>(4,4); // [4][4]
public:
Cords();
static int getX(void);
static int getY(void);
};
int Cords::Xcord[0][0] = 4234; //On these lines is the mistake
int Cords::Ycord[0][0] = 2342; //On these lines is the mistake
So I fixed the problem with a static constructor and I noticed that you are supposed to type [0,0] instead of [0][0]. I'm used to normal C arrays.
//Cords.h
ref class Cords {
private:
static array<int,2>^ Xcord = gcnew array<int,2>(4,4); // [4][4]
static array<int,2>^ Ycord = gcnew array<int,2>(4,4); // [4][4]
static Cords() { //static constructor to initialize values
Xcord[0,0] = 4234; // [0,0] instead of [0][0]
Ycord[0,0] = 2342;
...
}
public:
Cords();
static int getX(void);
static int getY(void);
};

I can't display variables of different types included in array

I have to do a program for college.
I have 3 classes already declared in the statement of the problem.
First class:
class piesa_a{
protected:
int id;
char *tip;
int pret;
};
Second class:
class piesa_b:public piesa_a
{
private:
float lungime;
bool bw;
};
Third class:
class piesa_c:public piesa_a
{
private:
int nr;
piesa_b *buf;
};
In main I need to create an array in which to store items such piesa_a, piesa_b, piesa_c. Then I have to sort items by price.
I have this code so far: http://pastebin.com/nx2FGSfe
The program is incomplete because it does not displays each item in the array.
I got stuck here. But if you display the array's elements when they are outside of it, it works.
SHORT: I have an error on line 143 and I want to solve it.
main.cpp:143:18: error: request for member ‘afisare’ in ‘*(v + ((unsigned int)(((unsigned int)i) * 4u)))’, which is of non-class type ‘piesa_a*’
The code is here:
#include <cstdlib>
#include<iostream>
#include<string.h>
using namespace std;
class piesa_a{
protected:
int id;
char *tip;
int pret;
public:
piesa_a()
{
id = 0;
tip = new char[1];
pret = 0;
}
piesa_a(int aidi, char *typ, int pretz)
{
id = aidi;
tip = new char[strlen(typ)+1];
strcpy(tip,typ);
pret = pretz;
}
piesa_a&operator =(piesa_a alta)
{
id = alta.id;
tip = new char[strlen(alta.tip)+1];
strcpy(tip,alta.tip);
pret = alta.pret;
return *this;
}
virtual void afisare()
{
cout<<"\n Piesa A: "<<id<<" "<<tip<<" "<<pret;
}
};
class piesa_b:public piesa_a
{
private:
float lungime;
bool bw;
public:
piesa_b():piesa_a(){lungime = 0;bw = 0;}
piesa_b(float lg,bool bl, int aid, char *tipi, int pretzz):piesa_a(aid,tipi,pretzz)
{
lungime = lg;
bw = bl;
}
piesa_b&operator =(piesa_b &c)
{
id = c.id;
tip = new char[strlen(c.tip)+1];
strcpy(tip,c.tip);
pret = c.pret;
lungime = c.lungime;
bw = c.bw;
return *this;
}
void afisare()
{
piesa_a::afisare();
cout<<"impreuna cu piesa B: "<<lungime<<" "<<bw<<"\n";
}
};
class piesa_c:public piesa_a
{
private:
int nr;
piesa_b *buf;
public:
piesa_c():piesa_a(){nr=0; buf = new piesa_b[nr];}
piesa_c(int n, piesa_b *bu,int aid, char *tipi, int pretzz):piesa_a(aid,tipi,pretzz)
{
nr = n;
buf = new piesa_b[nr];
for(int i=0;i<nr;i++)
buf[i]= bu[i];
}
piesa_c&operator =(piesa_c &alta)
{
id = alta.id;
tip = new char[strlen(alta.tip)+1];
strcpy(tip,alta.tip);
pret = alta.pret;
nr = alta.nr;
for(int i=0;i<alta.nr;i++)
buf[i] = alta.buf[i];
}
void afisare()
{
for(int i=0;i<nr;i++)
buf[i].afisare();
}
};
int main(int argc, char** argv) {
piesa_b *H;
H = new piesa_b[2];
piesa_a A(4,"TIPA",120);
piesa_b B(100,1,3,"TIPA",120);
H[0]=B;
H[1]=B;
piesa_c C(2, H,14,"TIPC",20);
piesa_a** v = new piesa_a*[3];
v[0] = &A;
v[1] = &B;
v[2] = &C;
for(int i=0;i<3;i++)
v[i].afisare();
return 0;
}
What's wrong?
In C++ (and current C), casts are almost always a sign that the programmer didn't know how to use the language as it is supposed to be used. If you need an array of 3 types of data, the cleanest solution is an array of objects of a class that is base to the 3. And if you want to display each item differently, you'll want to overload the << operator, so you just iterate over the array and go << on each item. Sorted by price means that the class includes a price field, and you use the sort from the standard template library, passing a comparison operation that just compares prices.