C++ run-time template constant - c++

I was trying to create a user-defined container type with using and private members in the class, which are not compile-time constants. The is not valid and complained by the compiler. Those private member constants will only be initialized at runtime. Is there such a remedy for this kind of scenario?
#include <vector>
#include <array>
#include <string>
#include <iostream>
class SudokuBoard
{
private:
Board _board_data;
int _BOX_SIZE;
int _BOARD_SIZE;
const int _MAX_VALUE = _BOARD_SIZE;
const int _NUM_CONSTRAINTS = 4;
public:
template <class T, int ROW, int COL>
using Matrix = std::array<std::array<T, COL>, ROW>;
using CoverMatrix = Matrix<int, _BOARD_SIZE * _BOARD_SIZE * _MAX_VALUE, _BOARD_SIZE * _BOARD_SIZE * _NUM_CONSTRAINTS>;
using Board = Matrix<int, _BOARD_SIZE, _BOARD_SIZE>;
SudokuBoard(const std::string& filename);
void set_board_data(int row, int col, int num) { _board_data[row][col] = num; }
int get_board_data(int row, int col) const { return _board_data[row][col]; }
Board get_board_data() const { return _board_data; }
int at(int row, int col) const { return _board_data[row][col]; }
// Prints the Sudoku board
friend void print_board(const SudokuBoard& board);
friend std::ostream& operator<< (std::ostream &out, const SudokuBoard& board);
int indexInCoverMatrix(int row, int col, int num);
int createBoxConstraints(CoverMatrix coverMatrix, int header);
int createColumnConstraints(CoverMatrix coverMatrix, int header);
int createRowConstraints(CoverMatrix coverMatrix, int header);
int createCellConstraints(CoverMatrix coverMatrix, int header);
void createCoverMatrix(CoverMatrix coverMatrix);
void convertToCoverMatrix(Board board, CoverMatrix coverMatrix);
};

The first issue you get, compiling this, with a placeholder class Board{}; is something like:
Compilation failed
For more information see the output window
x86-64 clang 12.0.1 - 405ms
:23:37: error: invalid use of non-static data member '_BOARD_SIZE'
using CoverMatrix = Matrix;
What this tells you is that the compiler needs to know at compile them about the sizes and types of your templates.
A first step is to make them static const. That way, the compiler knows at compile time:
static const int _BOARD_SIZE = 9;
static const int _MAX_VALUE = _BOARD_SIZE;
(constexpr give you other, more modern, options but this is a starting point)
Then, you'll probably want to have your SudokuBoard class itself templated on some type T. But I can't get there as you didn't provide the Board class.

Related

C++ Typedef inside classes using private members

I tried to customize some types inside a class by using private members, which are used to set the size of customized containers. But I received:
error: ‘CoverMatrix’ does not name a type
error: ‘Board’ does not name a type
How do I properly manipulate it?
#include <vector>
#include <array>
#include <string>
#include <iostream>
class SudokuBoard
{
private:
Board _board_data;
int _BOX_SIZE;
int _BOARD_SIZE;
const int _MAX_VALUE = _BOARD_SIZE;
const int _NUM_CONSTRAINTS = 4;
public:
template <class T, int ROW, int COL>
using Matrix = std::array<std::array<T, COL>, ROW>;
typedef CoverMatrix Matrix<int, _BOARD_SIZE * _BOARD_SIZE * _MAX_VALUE, _BOARD_SIZE * _BOARD_SIZE * _NUM_CONSTRAINTS>;
typedef Board Matrix<int, _BOARD_SIZE, _BOARD_SIZE>;
SudokuBoard(const std::string& filename);
void set_board_data(int row, int col, int num) { _board_data[row][col] = num; }
int get_board_data(int row, int col) const { return _board_data[row][col]; }
Board get_board_data() const { return _board_data; }
int at(int row, int col) const { return _board_data[row][col]; }
// Prints the Sudoku board
friend void print_board(const SudokuBoard& board);
friend std::ostream& operator<< (std::ostream &out, const SudokuBoard& board);
int indexInCoverMatrix(int row, int col, int num);
int createBoxConstraints(CoverMatrix coverMatrix, int header);
int createColumnConstraints(CoverMatrix coverMatrix, int header);
int createRowConstraints(CoverMatrix coverMatrix, int header);
int createCellConstraints(CoverMatrix coverMatrix, int header);
void createCoverMatrix(CoverMatrix coverMatrix);
void convertToCoverMatrix(Board board, CoverMatrix coverMatrix);
};
You already use using correctly to set up the Matrix type. You really should just keep doing that with the other types too:
using CoverMatrix = Matrix<int, _BOARD_SIZE* _BOARD_SIZE* _MAX_VALUE, _BOARD_SIZE* _BOARD_SIZE* _NUM_CONSTRAINTS>;
using Board = Matrix<int, _BOARD_SIZE, _BOARD_SIZE>;
But if you for some reason insist on mixing using and typedef, then the correct syntax is:
typedef Matrix<int, _BOARD_SIZE* _BOARD_SIZE* _MAX_VALUE, _BOARD_SIZE* _BOARD_SIZE* _NUM_CONSTRAINTS> CoverMatrix;
typedef Matrix<int, _BOARD_SIZE, _BOARD_SIZE> Board;
In other words:
using identifier = type;
typedef type identifier;
Also, do note that as #NathanOliver pointed out, your private int members are not compile time constants. So after you fix the typedef syntax the code still won't work - but you can put that in a new question if you need help with that. StackOverflow prefers only one topic per question.

Data recirculation between classes in C++ - error: '<class name>' was not declared in this scope

I am preparing a program with several classes, which have to exchange data between each other subsequently in the code. This results in inclusion of classes in each other headers. I have encountered a problem when it came to passing a vector of "Gas" objects to the "Thermal" class method and afterwards trying to pass a changed "Thermal" object to the "Gas" class method. I have tried forward including of the classes in each other header files, but with a miserable result. Maybe I did something wrong with that. Possibly a declaration of a pointers between class objects would solve a problem? I have tired this, but unfortunately I may lack of experience with pointers, as I failed as well.
Notice - When I comment out the #include "Thermal.h" from the "Gas" class, the code compiles successfully. However, then the diffusion method has to be commented out as well.
The compilier returns, as follows:
./src/Thermal.h:86:76: error: template argument 2 is invalid
./src/solution.cpp: In function 'void solution(const Ref::Reformer&,
const std::vector<Ref::Segment>&, std::ofstream*, std::ofstream*, std::ofstream*)':
./src/solution.cpp:92:40: error: no matching function for call to 'Ref::Thermal::
conduction(const Ref::Reformer&, Ref::Grid&, std::vector<Ref::Gas>&, Ref::Velocity&)'
T.conduction(reactor, grid, gases, vel);
^
In file included from ./src/Gas.h:20:0,
from ./src/solution.cpp:16:
./src/Thermal.h:86:8: note: candidate: void Ref::Thermal::conduction(const Ref::Reformer&,
const Ref::Grid&, const int&, const Ref::Velocity&)
void conduction(const Reformer& RE, const Grid& GD, const std::vector<Gas>& GAS,
const Velocity& VE);
^
./src/Thermal.h:86:8: note: no known conversion for argument
3 from 'std::vector<Ref::Gas>' to 'const int&'
Here is how I call the methods. Objects of class "Thermal" and "Gas" are created in the same .cpp file and are called subsequently. Their initialization requires construction and passing of a "Grid" class object, which is done in the same file as well.
Objects creation:
Grid grid(0.3, 0.052);
grid.setNX(90);
grid.setNR(15);
Thermal T(grid);
for(i = 0; i < 6; i++){
gases.push_back(Gas(i, grid));
}
Methods' call:
T.conduction(reactor, grid, gases, vel);
for(int i = 0; i < gases.size(); i++){
gases[i].diffusion(reactor, grid, vel, T);
}
Grid class declaration:
#ifndef REFORMING_CODE_REF_GRID_H
#define REFORMING_CODE_REF_GRID_H
#include "../input.h"
namespace Ref{
class Grid{
public:
Grid(const double& x1, const double& r1, const double& x0 = 0., const double& r0 = 0.){
xmin_ = x0;
xmax_ = x1;
rmin_ = r0;
rmax_ = r1;
}
void setNX(const int& nx){ //setting number of elements in the longitudinal direction
NX_ = nx;
ni_ = NX_ - 1;
}
void setNR(const int& nr){ //setting number of elements in the radial direction
NR_ = nr;
nj_ = NR_ - 1;
}
};
}//end of namespace
#endif //REFORMING_CODE_REF_GRID_H
Thermal class declaration:
#ifndef REFORMING_CODE_REF_THERMAL_H
#define REFORMING_CODE_REF_THERMAL_H
#include "../input.h"
#include "Reformer.h"
#include "Grid.h"
#include "Velocity.h"
#include "Gas.h"
namespace Ref{
class Thermal{
public:
Thermal(const Grid& grid){
NX_ = grid.NX();
NR_ = grid.NR();
}
void conduction(const Reformer& RE, const Grid& GD, const std::vector<Gas>& GAS, const Velocity& VE);
private:
int NX_; //quantity of elements in the X direction
int NR_; //quantity of elements in the R direction
std::vector<double> val_; //Temperature value (K)
std::vector<double> val_old_;
std::vector<double> s_; //Thermal source
};
} //end of namespace
#endif //REFORMING_CODE_REF_THERMAL_H
Conduction method definition:
#include "Thermal.h"
namespace Ref{
void Thermal::conduction(const Reformer& RE, const Grid& GD,
const std::vector<Gas>& GAS, const Velocity& VE){}
}
Gas class declaration:
#ifndef REFORMING_CODE_REF_GAS_H
#define REFORMING_CODE_REF_GAS_H
#include "../input.h"
#include "Reformer.h"
#include "Grid.h"
#include "Velocity.h"
#include "Thermal.h"
namespace Ref{
class Gas{
public:
Gas(const int id, const Grid& grid){
id_ = id;
NX_ = grid.NX();
NR_ = grid.NR();
}
void diffusion(const Reformer&, const Grid&, const Velocity&, const Thermal&);
private:
int id_;
int NX_;
int NR_;
};
} //end of namespace
#endif //REFORMING_CODE_REF_GAS_H
Diffusion method definition:
#include "Gas.h"
namespace Ref{
void Gas::diffusion(const Reformer& RE, const Grid& GD,
const Velocity& VE, const Thermal& T){}
} //end of namespace
You could try using forward declarations and moving the #include to the end of the header. ( your file wouldn't be included twice because of the header guards )
Minimal compiling example:
//RecursiveA.h
#ifndef RECURSIVEA_H
#define RECURSIVEA_H
class RecursiveA {
public:
void workOnB(const class RecursiveB &);
};
#include "RecursiveB.h"
#endif // RECURSIVEA_H
//RecursiveB.h
#ifndef RECURSIVEB_H
#define RECURSIVEB_H
class RecursiveB {
public:
void workOnA(const class RecursiveA &);
};
#include "RecursiveA.h"
#endif // RECURSIVEB_H
//RecursiveA.cpp
#include "RecursiveA.h"
void RecursiveA::workOnB(const RecursiveB &b){
}
//RecursiveB.cpp
#include "RecursiveB.h"
void RecursiveB::workOnA(const RecursiveA &a){
}

C++ 'unknown type name' and 'use of undeclared identifier' errors

I am writing a small program, for a school project, that emulate a shared editor (like Google Docs)
I've written all the classes that I need but when I try to build the program I get this errors:
error: unknown type name 'NetworkServer'
NetworkServer &_server;
error: use of undeclared identifier 'SharedEditor' std::vector<SharedEditor*> SEditors;
error: expected expression std::vector<SharedEditor*> SEditors;
error: unknown type name 'SharedEditor' int connect(SharedEditor* sharedEditor);
Here are my .h files
NetworkServer.h
#include <vector>
#include <queue>
#include "SharedEditor.h"
#include "Message.h"
class NetworkServer {
private:
std::vector<SharedEditor*> SEditors;
std::vector<int> idEditors;
std::queue<Message> messages;
public:
int connect(SharedEditor* sharedEditor);
int disconnect(SharedEditor* sharedEditor);
void send(const Message& m);
void dispatchMessages();
};
SharedEditor.h
#include "NetworkServer.h"
#include "Message.h"
#include "Symbol.h"
class SharedEditor {
private:
NetworkServer& _server;
int _siteId{};
std::vector<Symbol> _symbols;
int _counter;
public:
SharedEditor() = delete;
SharedEditor(NetworkServer& server);
void localInsert(int index, char value);
void localErase(int index);
void process(const Message& m);
std::string to_string();
int getSiteId() const;
};
Symbol.h
#include <vector>
class Symbol {
private:
char value;
int idClient;
int num;
std::vector<int> pos;
public:
Symbol(char value, int client, int num, std::vector<int> pos);
char getValue() const;
int getIdClient() const;
int getNum() const;
const std::vector<int> &getPos() const;
};
Message.h
#include <vector>
class Message {
bool insert; // true --> insert || false --> delete
int _siteId;
int num;
char value{};
std::vector<int> pos;
public:
Message(bool insert, int siteId, int num, char value, std::vector<int> pos);
Message(bool insert, int siteId, int num);
bool isInsert() const;
int getSiteId() const;
int getNum() const;
char getValue() const;
const std::vector<int> &getPos() const;
};
I don't understand where I am doing something wrong. BTW I am using CLion

Error: some class is not a template

I have a header file Algo.h. It has the following content:
#include <iostream>
#include <fstream>
#include <math.h>
#include <float.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
//some static functions
// ...
template <class Type> class Algo{
int
public:
Algo(int size, int num, int plth, int theN, float** theAg, int theLN,
float* theIn, float theeEps = 1E-3, float theEpsilonLR = 1E-3,
int theCycle = 30, bool DebInf = false, int theT = -1, int** theX = 0,
const char* theFileName = 0, const char* theFileNameChar = 0);
~Algo();
//some methods
//...
};
//Constructor
template <class Type> Algo<Type>::Algo(int size, int num, int plth, int theN, float** theAg, int theLN,
float* theIn, float theeEps = 1E-3, float theEpsilonLR = 1E-3,
int theCycle = 30, bool DebInf = false, int theT = -1, int** theX = 0,
const char* theFileName = 0, const char* theFileNameChar = 0){
//...
}
// ...
Then I'd like to usel it in main.cpp:
#include "Algo.h"
#include <float.h>
#include <time.h>
#include <stdlib.h>
#include <string>
#include <iostream>
using namespace std;
Algo<int>* construct1(const int & rt, float** & rm); //error: Algo is not a template
Algo<int>* construct2(const int & rte, float** & rm, Algo<int>* & the1, const bool & rob1); //error: Algo is not a template
//...
int main(){
//...
return 0;
}
It seems that everything should work fine, but I always get this error:
Algo is not a template.
Do you have any ideas how to fix it?
there is "int" which should not be there in your code. delete it, please.
template <class Type> class Algo{
int // here should be deleted
public:
...
constructor of Algo has many default params, but when you define this function, these default params should not be set value in param-list. you can make the constructor definition as follows:
template <class Type> Algo<Type>::Algo(int size, int num, int plth, int theN, float** theAg, int theLN, float* theIn, float theeEps, float theEpsilonLR, int theCycle, bool DebInf, int theT, int** theX, const char* theFileName, const char* theFileNameChar)
{
//...
}
do these 2 fixs, it will works.( I have try it on my computer~ )
I don't think this is the only problem, but pay attention to how you attempt to use it.
The constructor:
Algo(int size, int num, int plth, int theN, float** theAg, int theLN,
float* theIn, float theeEps = 1E-3, float theEpsilonLR = 1E-3,
int theCycle = 30, bool DebInf = false, int theT = -1, int** theX = 0,
const char* theFileName = 0, const char* theFileNameChar = 0);
Has many parameters. The first 7 are required, the remainder have default values and are optional. However, when you try and instantiate an instance:
Algo<int>* construct1(const int & rt, float** & rm); //error: Algo is not a template
Algo<int>* construct2(const int & rte, float** & rm, Algo<int>* & the1, const bool & rob1); //error: Algo is not a template
You are passing either 2, or 4 parameters. There is no matching overload.
You need to provide at least the first 7 parameters.

Getter returning 2d array in C++

this is my first post on SO, even though i've spent some time already here.
I've got here a problem with a function returning a 2d array. I have defined a private 2d int array property int board[6][7] in my Game class, but i don't know how to create a public getter for this property.
These are relevant parts of my game.h:
#ifndef GAME_H
#define GAME_H
class Game
{
public:
static int const m_rows = 6;
static int const m_cols = 7;
Game();
int **getBoard();
private:
int m_board[m_rows][m_cols];
};
#endif // GAME_H
Now what I would like is something like this in game.cpp (cause I thought array name without brackets is a pointer to first element, obviously it doesn't work with 2d arrays) :
int **Game::getBoard()
{
return m_board;
}
So that i can put this for example in my main.cpp:
Game *game = new Game;
int board[Game::m_rows][Game::m_cols] = game->getBoard();
Can anybody help me, what should i put in my game.cpp ?
Thanks!
You cannot pass arrays by value into and out of functions. But there's various options.
(1) Use a std::array<type, size>
#include <array>
typedef std::array<int, m_cols> row_type;
typedef std::array<row_type, m_rows> array_type;
array_type& getBoard() {return m_board;}
const array_type& getBoard() const {return m_board;}
private:
array_type m_board;
(2) Use the correct pointer type.
int *getBoard() {return m_board;}
const int *getBoard() const {return m_board;}
private:
int m_board[m_rows][m_cols];
An int[][] has no pointers involved. It isn't a pointer to an array of pointers to arrays of integers, it's an array of an array of integers.
//row 1 //row2
[[int][int][int][int]][[int][int][int][int]]
Which means one int* points to all of them. To get to a row offset, you'd do something like this:
int& array_offset(int* array, int numcols, int rowoffset, int coloffset)
{return array[numcols*rowoffset+coloffset];}
int& offset2_3 = array_offset(obj.getBoard(), obj.m_cols, 2, 3);