The error is : "member matrix::rows is not a type name" and "member matrix::init is not a type name". If it compiles successfully I shall have a matrix rows = ROWS and columns = COLS. What am i doing wrong here:
#include <vector>
class matrix
{
int ROWS{}, COLS{}, init{-1};
std::vector<std::vector<int>> table(ROWS, std::vector<int>(COLS, init));
};
As John Zwinck points out, you need curly brackets. Why? Because, otherwise, the compiler takes
std::vector<std::vector<int>> table(ROWS, std::vector<int>(COLS, init));
as the definition of a member function, called table, returning a std::vector<std::vector<int>> and taking a first (unnamed) parameter of type ROWS. At which point the compiler goes "Ugh, I don't know the type ROWS, let me throw a compilation error".
You can google Most Vexing Parse. https://en.wikipedia.org/wiki/Most_vexing_parse
You can write it like this:
class matrix
{
static constexpr int ROWS{}; // TODO: change to non-zero
static constexpr int COLS{}; // TODO: change to non-zero
static constexpr int init{-1};
std::vector<std::vector<int>> table{ROWS, std::vector<int>(COLS, init)};
};
I don't understand the usage of the vector of vectors for this case.
For such a case, I would propose to use a plain array.
template<int N, int M, typename D> struct Matrix {
public:
D get(int i, int j) {
return _data[index(i,j)];
}
void set(int i, int j, D v) {
_data[index(i,j)] = v;
}
private:
int index(int i, int j){
return i*N + j;
}
D _data[N*M];
};
So you don't really need std::vector. Just add some checks and you are good.
Related
I have created a class matrix that besides having some member functions, operators and a constructor has two variables:
int m, which is the dimension (side length) of the quadratic matrix
double a[], which contains the elements of the matrix.
As long as I only create one matrix object A all seem to work fine and all my member operators and functions work as they should.
My problem is that once I create a second object B of the class matrix the variables of object A changes as well.
The relevant code is as follows:
class Matrix{
private:
const int m;
double a[];
public:
Matrix(int inpm);
void fillMatrix(const double inpa[]);
};
Matrix::Matrix(int inpm): m(inpm){
a[impm*inpm];
}
void Matrix::fillmatrix(const double inpa[]){
for (int i ; i<m*m ; i++){
a[i]=inpa[i];
}
}
int min =2;
double ain[min*min] = {1,2,3,4};
double bin[min*min] = {5,6,7,8};
Matrix A(min);
Matrix B(min);
A.fillMatrix(ain);
//A looks precisely as it should here:
//m=2, a={1,2,3,4}
B.fillMatrix(bin);
//Here B looks as it should but A has changed to:
//m=0, a={7,8,3,4}
obviously the change to the first object occur when I run fillMatrix() for the second object but I cannot figure out why, especially since m is a constant integer.
I'm really stuck so grateful for all help.
PS: I use another member function "void printMatrix();" using std:cout to look at the values of m and all elements in a.
a[impm*inpm]; This does not do what you think. GCC even warns with statement has no effect.
a remains uninitialized here and you run into undefined behavior when you try to access a[i]
class Matrix{
private:
const int m;
double *a;
....
and
Matrix::Matrix(int inpm): m(inpm)
{
a = new double[inpm*inpm];
}
and then remember to delete
Matrix::~Matrix()
{
delete a;
}
c++ arrays are not actually allowed to variable. There are plenty of sources about why variable length arrays (vla's) are not allowed. If you wan't a dynamic length array with size chosen at run time, you need to allocate some memory:
double *a;
...
a = new double[inpm*inpm];
But this sucks! Now you have to remember to delete and access correctly and everything. You could wrap this memory in a class to control this, and since this is such a good idea, c++ provides this as standard. It is called std::vector. Your code will happily reduce to this:
class Matrix{
private:
const int m;
std::vector<double> a;
public:
Matrix(int inpm) : m(inpm), a(m * m) {}
The problem is because of your array declaration. people used to call that kind of array declaration as "flexible array declaration.". And it wouldn't work as you expected. plus there are certain rules to follow while using a flexible array.
But if you want to create a dynamic array you can use malloc to create array dynamically.
I've noticed a few issues with your code. The first few were already mentioned by others such as your member double a[]; This is uninitialized and C++ does not allow for variable length vectors. To resolve this there are two possible solutions which I'll discuss shortly. The other issue that others have mentioned is that in your Matrix::fillMatrix() function the variable in your for loop i is also uninitialized, so i can be anything and this will lead to undefined behavior.
A few issues that have not been mentioned by others are as follows:
In your constructor definition you are trying to initialize m with a[impm*inpm] I think this might be a typo on your part. Another one is you declare your function as ::fillMatrix() but you define it outside of the class declaration as ::fillmatrix(). Again I think this might be just a typo on your part.
As for the issue above with the use of arrays in C++ the easiest way to do this is what others have already stated and that is to use std::vector<type>.
The other way is to write a class that works similarly to std::vector but has the mechanics of a matrix. Your class would look something like this using templates: If you want a variable length container at runtime you have to know it's size at compile time using templates here can help as the template has to be deduced at compile time upon instantiation!
template<class T, unsigned N>
class Matrix {
private:
static const unsigned Stride = N;
static const unsigned Size = Stride * Stride;
T data[Size] = {};
public:
Matrix() {};
void fillMatrix( const T* dataIn );
void printMatrix();
};
template<class T, unsigned N>
void Matrix<T, N>::fillMatrix( const T* dataIn ) {
for( unsigned int i = 0; i < Size; i++ ) {
this->data[i] = dataIn[i];
}
}
template<class T, unsigned N>
void Matrix<T, N>::printMatrix() {
for( unsigned int i = 0; i < Stride; i++ ) {
for( unsigned int j = 0; j < Stride; j++ ) {
std::cout << this->data[i*Stride + j] << " ";
}
std::cout << '\n';
}
}
int main() {
// 2x2 = 4
double ain[4] = { 1,2,3,4 };
double bin[4] = { 5,6,7,8 };
Matrix<double, 2> A;
Matrix<double, 2> B;
A.fillMatrix( ain );
A.printMatrix();
std::cout << '\n';
B.fillMatrix( bin );
B.printMatrix();
std::cout << '\n';
// test A again
A.printMatrix();
std::cout << '\n';
B.printMatrix();
std::cout << '\n';
// Try it with other types
// 3x3 = 9
char data[9] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' };
Matrix<char, 3> C;
C.fillMatrix( data );
C.printMatrix();
std::cout << '\n';
return 0;
}
Output:
1 2
3 4
5 6
7 8
1 2
3 4
5 6
7 8
a b c
d e f
g h i
With this type of design using templates you are not restricted to just using a single type such as int, float etc. You can even use User Defined Types. The only thing here that you would need to consider is any kind of operators you may have. Also the way this class is written it will always create a MxM matrix which will always be a square matrix. If you need a non square matrix; you can just add to this class by adding in a 2nd unsigned constant value to the template parameter list and renaming them accordingly for MxN. Then just substitute where they belong in the math. It would look something like this:
template<class T, unsigned M, unsigned N>
class Matrix {
private:
static const unsigned Row = M;
static const unsigned Col = N;
static const unsigned Size = Row * Col;
T data[Size] = {};
};
Now how you label them might depend on if you want Row-Col major or Col-Row major...
I have a Matrix class that looks something like this:
template<int R, int C>
class Matrix{
public:
double matrix[R][C];
Matrix(double n = 0)...{}
...
};
Matrix<2,3> m;
How do I initialize the array when creating a new matrix with the n in the c'tor, without iterating over the whole array cell by cell?
I've read here some answers about something called memset, but I can't use it at the moment (it's a part of homework assignment).
My advice is to use std algorithms wherever possible:
std::for_each(std::begin(matrix), std::end(matrix),
[n](double* row) { std::fill_n(row, C, n); } );
Full example:
template<int R, int C>
class Matrix{
public:
double matrix[R][C];
Matrix(double n = 0) {
std::for_each(std::begin(matrix), std::end(matrix),
[n](double* row) { std::fill_n(row, C, n); } );
}
};
Iterate over the whole array cell be cell using clear, simple, obvious code. If your compiler is sensible (and why use it if it's not) it will understand precisely what you are doing and substitute in the optimal initialization mechanism for your platform.
I'm trying to perform a strided access to a submatrix with a single index. I need this for a library I'm working on which uses expression templates. I have worked out the following class, where the access is performed by the overloaded operator[], see below:
template <class A, class Type>
class SubMatrixExpr
{
private:
int Rows_; // Rows of the SubMatrix
int Columns_; // Columns of the SubMatrix
int Rows_up_; // Rows of the original Matrix
int Columns_up_; // Columns of the original Matrix
int a_, c_; // Starting indices of the SubMatrix as evaluated in the original Matrix
int rowstep_, columnstep_; // Stride along rows and columns for the original matrix
A M_;
public:
SubMatrixExpr(A &M, int Rows_up, int Columns_up, int Rows, int Columns, int a, int rowstep, int c, int columnstep) :
a_(a), c_(c), M_(M),
Rows_(Rows),
Columns_(Columns),
Rows_up_(Rows_up), Columns_up_(Columns_up),
rowstep_(rowstep), columnstep_(columnstep) { }
inline const Type& operator[](const int i) const
{
const int LocalRow = i/Columns_;
const int LocalColumn = i%Columns_;
const int GlobalRow = a_+rowstep_*LocalRow;
const int GlobalColumn = c_+columnstep_*LocalColumn;
return M_[IDX2R(GlobalRow,GlobalColumn,Columns_up_)];
}
inline Type& operator[](const int i)
{
// Similar to above
}
};
where
#define IDX2R(i,j,N) (((i)*(N))+(j))
The overloaded operator[] works correctly, but is computationally very expensive.
Is there any way to better implement the overloaded operator[]?
Thanks a lot in advance.
The only way you may got speedup is if you now the size of the matrices and sub-matrices at compile time. Then using template / constexpr may speedup things. For example if the size is known to be a power of 2 at compile time, the compiler will be able to replace division by shift.
I need to create a function that has a parameter which is a multi-dimensional array with two dimensions being user-specified, e.g.
int function(int a, int b, int array[a][b])
{
...
}
How would I do that in C++ ?
Are the dimensions known at compile-time? In that case, turn them into template parameters and pass the array by reference:
template<int a, int b>
int function(int(&array)[a][b])
{
...
}
Example client code:
int x[3][7];
function(x);
int y[6][2];
function(y);
Assuming the dimensions are not known at compile time, you emulate a two dimensional array with a one dimensional array:
int& getat(int x, int y, int r, int c, int *array) {return array[y*c+x];}
int function(int a, int b, int *array) {
getat(4, 2, a, b, array) = 32; //array[4,2] = 32
}
or, for safety, wrap it all in a class:
template <class T>
class array2d {
std::vector<T> data;
unsigned cols, rows;
public:
array2d() : data(), cols(0), rows(0) {}
array2d(unsigned c, unsigned r) : data(c*r), cols(c), rows(r) {}
T& operator()(unsigned c, unsigned r) {
assert(c<cols&&r<rows);
return data[r*cols+c];
}
};
or, best yet, use Boost's Multidimensional Array, which will be better than anything mere mortals could write.
I'm not sure if this work, because your question and code are not the same, according to your code the function can have 3 parameters, so this would work:
int function(int a, int b, int** &array)
{
array = new int*[a];
for (int i =0;i<a;i++)
array[i] = new int[b];
// I don't know why you are returning int, probably doing something here....
}
However your question says that your function can take only one parameter, so:
if the dimensions are known at compile time, then Fred's Answer is the best (it charmed me in fact! :) ).
if not, I can't see any possible solution that allows passing more than one user-specified value other than encapsulating all these values in one object.
Like this:
class Foo {
public:
Foo(int d1, int d2)
{ a = d1; b = d2; }
int a,b;
int** array;
};
int function(Foo &f)
{
f.array = new int*[f.a];
for (int i = 0;i<f.a;i++)
f.array[i] = new int[f.b];
// I don't know why you are returning int, probably doing something here....
}
Though I find it a bad idea, in fact the function could be a parameterless method instead:
class Foo {
public:
Foo(int d1, int d2)
{ a = d1; b = d2; }
void Create() // Or could do this right in the Constructor
{
array = new int*[a];
for (int i = 0;i<a;i++)
array[i] = new int[b];
}
private:
int a,b;
int** array;
};
Still this is a bad idea, because you are reinventing the wheel, as there are a perfect class in the STL to do all the work for you:
vector< vector<int> > v; // Now v is a 2D array
I'd like to use sort() to do the following
I have a text char[] T which is (private) member of a class. The text has length n.
I also ave an array int[] P that contains the first n integers.
I'd like to std::sort P such that the lexicographic order among suffixes of T are preserved
i.e., for any i < j we have that T[P[i]...n] is lex smaller than T[P[j]...n].
I'm able to do it when char[] T is a global variable by defining
bool myfunction (int i,int j) {
int m = i, l = j;
while(m<n and l <n) {
if(T[m] != T[l]) return (T[m]<T[l]);
m++; l++;
}
return (m<l);
}
and calling std::sort(P, P+n, myfuction)
I'm in truble when T is a member of an object (and sort is called by a method of that object).
How can I define myfunction so that T is visible?
Should it be member of that object? If yes, how?
Thank you very much.
Edit: bool instead of int
As you guessed, one way to do it is by defining yourfunction() as a public member of that class.
Example:
#include <algorithm>
#include <vector>
using namespace std;
class T
{
private:
int value;
public:
T()
{
value = rand() % 100;
}
static bool Compare(const T &a, const T &b)
{
return a.value < b.value;
}
};
int main(int argc, char** argv)
{
vector<T> data;
//add some data
for (int i=0; i<10; i++)
data.push_back(T());
//sort using static method that can access private attributes
std::sort(data.begin(), data.end(), T::Compare);
}
If sort represents std::sort, the function that you are using as predicate is wrong for a couple of reasons, the first of which is that the returned type from the function should be a bool and not an int.
The next thing that is wrong is that the predicate is required to be consistent, that is, given two inputs a and b the result of predicate( a, b ) must be either true or false and always the same. If that condition is not met, the result of calling sort will be undefined, possibly including an infinite loop.
The approach (rather than the predicate itself) is probably not good either, as the number of times that the predicate will be called depends on the input data, and the results of the different calls to the predicate (until the algorithm thinks, that according to your partial order, the sequence is sorted).
You probably need a functor object:
struct myfunctor {
const char *T;
size_t n;
myfunctor(const char *T, size_t n) : T(T), n(n) {}
bool operator()(int i, int j) {
// stuff using T and n
}
// Optionally, something along these lines, I haven't tested it
template <size_t N> myfunctor(const char (&x)[N]) : T(&x[0]), n(N) {}
template <size_t N> myfunctor(char (&x)[N]) : T(&x[0]), n(N) {}
};
SomeObjectContainingT x;
std::sort(P, P+n, myfunctor(x.T, x.n));
Or if x.T is an actual array rather than just a pointer, the template constructors will capture the array size from the type, no need for a second parameter:
std::sort(P, P+n, myfunctor(x.T));
Edit: sorry, missed that T is private. I think you have two issues here, scope and accessibility. The functor solves the scope problem, now for the accessibility.
If you want external functions to access T, x must provide a means to access it. For example, it could return the functor object:
class SomeObjectContaining T {
char T[23];
public:
myfunctor comparator() { return myfunctor(T); }
};
std::sort(P, P+n, x.comparator());
Or you could mess about with friend: define your functor class as a friend of SomeObjectContainingT, then pass the object to its constructor rather than the array.