Weird error in Turbo C++ IDE - Class template related question - c++

Basically I'm trying to compile a template class which is meant to represent a table for adding up polynomials. As a result of this the table needs to be nullable.
This is the sort of thing I am trying to represent http://www.mathsisfun.com/algebra/polynomials-adding-subtracting.html.
And this is the template which is meant to do it:
template <class T> class TableWithBlanks : public Table<T> {
public:
TableWithBlanks( const int width, const int height ) : w(width), h(height), table_contents( new t_node[width][height]
{
table_contents = new t_node[width][height];
// Go through all the values and blank them.
for( int i = 0; i < w; i++)
{
for( int a = 0; a < h; a++)
{
table_contents[i][a].value_ptr = NULL;
}
}
}
void set_value( const int width, const int height, const T* table_value_ptr)
{
if( width <= w && height <= h )
{
table_contents[w][h] = table_value_ptr;
}
}
T* get_value( const int width, const int height)
{
if( width <= w && height <= h )
{
return table_contents[width][height];
}
}
private:
typedef struct node {
T* value_ptr;
} t_node;
t_node** table_contents;
int w;
int h;
};
And this is the error I am getting:
[C++ Error] TableWithBlanks.h(16):
E2034 Cannot convert
'TableWithBlanks::node
( *)[1]' to
'TableWithBlanks::node
* *'
The PolynomialNode class is a class which is a linked list, where each node in the list represent the terms in a simple polynomial - I don't need to go into details.

In this line, you're trying to dynamically construct a two-dimensional array:
table_contents = new t_node[width][height];
but C++ doesn't work this way. For an example of how to allocate two-dimensional arrays, see this question, for example.

Related

Passing pointers of vectors with structures C++

I've declared the following function in C++
void setCellInfo (CELL_MESH* target, int Global_ID, int node0,vector<NODE_MESH *>* NodeStore, vector<CELL_MESH *>* CellStore) {
CellStore->push_back(target); //No Errors
target->Global_ID = Global_ID; //No Errors
if (node0 != 0) {
target->node[0] = NodeStore[vector<NODE_MESH *>::size_type(node0)]->ID; //ERROR 1
target->node_pointers[0] = NodeStore[vector<NODE_MESH *>::size_type(node0)]; //ERROR 2
}
}
ERROR1: Gives me a "No member named 'ID' in 'std::vector<NODE_MESH *>'" for the target->node[] attributions although its the entities from the pointers within the vector that have this ID member. Since I'm trying to get a specific entity in the vector using NodeStore[value], I would think it would work.
ERROR2: Gives me "Assigning to 'NODE_MESH *' from incompatible type 'vector<NODE_MESH *>'" for all the target->node_pointers attributions. This seems to be the same problem but with pointers directly (without the ID member).
the NodeStore and CellStore vectors a defined as follows outside the function
vector<NODE_MESH*> NodeStore;
vector<CELL_MESH*> CellStore;
I then try to use the function like this, with 'i' being the int Global_ID and 'nodes_x*y+x' being some integer.
CELL_MESH *newCell = new CELL_MESH;
setCellInfo (&newCell, i, nodes_x*y+x, &NodeStore, &CellStore);
I've tried many different alterations to pointers but can't get it work. Would you know how to ?
Here's a simplified complete version:
#include <vector>
using namespace std;
typedef struct NODE_MESH{
int ID;
}NODE_MESH;
typedef struct CELL_MESH{
int Global_ID;
NODE_MESH* node_pointers[4];
int node[4];
}CELL_MESH;
vector<NODE_MESH*> NodeStore;
vector<CELL_MESH*> CellStore;
double nodes_y = 5;
double nodes_x = 4;
int cells_y = 4;
int cells_x = 3;
void setCellInfo (CELL_MESH* target, int Global_ID, int node0,vector<NODE_MESH *>* NodeStore, vector<CELL_MESH *>* CellStore) {
CellStore->push_back(target); //No Errors
target->Global_ID = Global_ID; //No Errors
if (node0 != 0) {
target->node[0] = NodeStore[vector<NODE_MESH *>::size_type(node0)]->ID; //ERROR 1
target->node_pointers[0] = NodeStore[vector<NODE_MESH *>::size_type(node0)]; //ERROR 2
}
}
int main() {
int i = 0;
for (double y = 0; y < nodes_y; y++) {
for (double x = 0; x < nodes_x; x++) {
NODE_MESH *newNode = new NODE_MESH;
NodeStore.push_back(newNode);
newNode -> ID = i;
i++;
}
}
i = 0;
for (int y = 0; y < cells_y; y++) { //nodes_y since horizontal faces are aligned with nodes horizontaly (same y)
for (int x = 0; x < cells_x; x++) { //x coordinate for horizontal faces is in-between nodes so 0.5 with count for faces
CELL_MESH *newCell = new CELL_MESH;
setCellInfo (newCell, i, nodes_x*y+x, &NodeStore, &CellStore);
i++;
}
}
return 0;
}
Given a variable T* t, the syntax t[x] is equivalent to *(t+x), which is the cause of this confusion. Concretely, NodeStore[vector<NODE_MESH *>::size_type(node0)] is of type vector<NODE_MESH *>& instead of an element of the NodeStore as you expected.
Change your code to take variables by reference instead:
void setCellInfo (CELL_MESH* target, int Global_ID, int node0,vector<NODE_MESH *>& NodeStore, vector<CELL_MESH *>& CellStore) {
CellStore->push_back(target); //No Errors
target->Global_ID = Global_ID; //No Errors
if (node0 != 0) {
target->node[0] = NodeStore[node0]->ID;
target->node_pointers[0] = NodeStore[node0];
}
}
The call is then simply
setCellInfo (&newCell, i, nodes_x*y+x, NodeStore, CellStore);
Alternatively, you will need to dereference the pointer before indexing:
(*NodeStore)[node0]->ID
Final Solution:
void setCellInfo (CELL_MESH* target, int Global_ID, int node0,vector<NODE_MESH *>& NodeStore, vector<CELL_MESH *>& CellStore) {
CellStore.push_back(target);
target->Global_ID = Global_ID;
if (node0 != 0) {
target->node[0] = NodeStore[node0]->ID;
target->node_pointers[0] = NodeStore[node0];
}
}
With this when using it:
CELL_MESH *newCell = new CELL_MESH;
setCellInfo (newCell, i, nodes_x*y+x, NodeStore, CellStore);

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

Rectangle Class and Templates C++

I'm trying to write a code that creates a rectangle class and also create two classes which compare the perimeter and the area of two rectangles and return the larger of the two. I keep getting errors that there is an expected ';' in places which I don't think they belong. Any suggestions?
#include <cstdlib>
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
template <typename Object, typename Comparator>
const Object & findMax( const vector<Object> & arr, Comparator isLessThan )
{
int maxIndex = 0;
for( int i = 1; i < arr.size(); ++i )
if( isLessThan( arr[ maxIndex], arr[ i ] ) )
maxIndex = i;
return arr[ maxIndex ];
}
class AreaComparator
{
public:
int compare( Rectangle lhs, Rectangle rhs ) const
{ return double.compare( lhs.getArea(), rhs.getArea() ); }
};
class PeriComparator
{
public:
int compare( Rectangle lhs, Rectangle rhs ) const
{ return double.compare( lhs.getPerimeter(), rhs.getPerimeter() ); }
};
class Rectangle
{
double length, width;
public:
Rectangle( double l, double w)
{
l = length;
w = width;
}
double getArea()
{
return length * width;
}
double getPerimeter()
{
return ( 2 * length) + ( 2 * width );
}
};
int main(int argc, char *argv[])
{
cout <<(findMax(new Rectangle[] { new Rectangle(1, 5), new Rectangle(2, 3) }, new AreaComparator())) << endl;
cout <<(findMax(new Rectangle[] { new Rectangle(1, 5), new Rectangle(2, 3) }, new PeriComparator())) << endl;
system("PAUSE");
delete Rectangle[];
delete AreaComparator[];
delete PeriComparator[];
return EXIT_SUCCESS;
}
Any suggestions?
Building on #Logicrat's comment, I would suggest assigning all your new objects to local variable names, and then splitting up your cout statements into shorter pieces (multiple short cout's replacing each long cout). If the ; problem persists, you will more easily see why.

Class of dynamic array

I've been working on a C++ exercise and I was unable to figure out how to do it correctly, let me explain it:
I made this class based on the 1st question of the exercise
class cylinder
{
private:
float height;
float radius;
char * label;
public:
cylinder(float, float, char *);
cylinder();
cylinder(const cylinder &);
~cylinder();
};
The 2nd question was:
Create a new class "form3D" contain cylinders (dynamic array of cylinder)
How to make a default constructor & constructor with parameters?
This is what I did:
class forme3d
{
cylinder * tab;
int tabsize;
public:
forme3d();
forme3d(cylinder * , int);
~forme3d();
};
forme3d::forme3d(cylindre * c, int t)
{
cylindre * tab = new cylindre[t];
for (int i = 0; i < t; ++i)
{
tab[i] = c[i];
}
}
This cause an error about "operator=" not defined for this line "tab[i] = c[i];"

C++ - Need to pass a 2D array, but must be dynamically sized

I am using a C++ library that requires that I pass it a 2D array. Their code example gives a statically sized array like this:
double data[][2] = {
{ 10, 20, },
{ 13, 16, },
{ 7, 30, },
{ 15, 34, },
{ 25, 4, },
};
But I need to pass run-time sized data. So I was attempting to do this:
// unsigned numBins is passed in to this function and set at run time
double** binData = new double*[numBins];
for(unsigned i=0; i < numBins; ++i) {
binData[i] = new double[2];
}
//Set the data with something like
// binData[7][0] = 10;
// binData[7][1] = 100;
//Later, diligently delete my data...
However, this fails in the library I am using. It ends of graphing some garbage numbers.
I understand that arrays are not pointers. And the library may be getting confused doing a "sizeof" somewhere.
If I am unable to change this library (it's 3rd party), how do I go about passing it dynamically sized data?
Thanks,
Maddie.
Probably the API expects a pointer to the first element of what it assumes is a flattened representation of a 2D array.
So the easy approach is as follows:
template<typename T>
struct FlatVectorAs2D {
private:
size_t width;
size_t height;
std::vector<T> flat_vec;
public:
std::vector<T>& base() { return flat_vec; }
std::vector<T> const& base() const { return flat_vec; }
size_t w() const { return width; }
size_t h() const { return height; }
T* operator[]( size_t index1 ) {
return &flat_vec[index1*height];
}
T const* operator[]( size_t index1 ) const {
return &flat_vec[index1*height];
}
FlatVectorAs2D( size_t w = 1, size_t h = 1 ):width(w), height(h) {
flat_vec.resize(w*h);
}
void resize( size_t w, size_t h ) {
width = w;
height = h;
flat_vec.resize(w*h);
}
T* raw() { return flat_vec.data(); }
T const* raw() const { return flat_vec.data(); }
};
Use:
void api_function(double* d);
int main() {
size_t width = 50;
size_t height = 100;
FlatVectorAs2D<double> buffer( width, height );
buffer[0][1] = 1.0;
api_function( buffer.raw() );
}
naturally this will depend on how exactly the API works.
But if my guess is right, this will help.
Try this:
typedef double two_doubles[2];
int main()
{
two_doubles * p = new two_doubles[300];
// ...
delete[] p;
}
Now p points to the first subarray of an array of 200 units of two doubles. That is, p[i] is a double[2], and p[i][0], p[i][1] are its member elements.
(Even better to use std::unique_ptr<two_doubles[]> p(new two_doubles[300]); and forget about the memory management.)