I tried a variable Args. The Matrix class works with int but when i use double i got wrong values with 23 when i dont convert it. I read that other types are automaticly converted
#include "matrix.h"
//#include "coordinate_sys.h"
int main(){
//Coordinate_3d<double>Coordinate_3(1,2,3);
//Coordinate_3.print_console();
Matrix<double>sick_matrix(2,2,4,20.5,(double)23,23,0);
sick_matrix.print_console();
while(1){}
return 0;
}
#ifndef MATRIX_H
#define MATRIX_H
#include <iostream>
#include <cstdarg>
template<typename T>
class Matrix{
private:
T * arr_ptr;
unsigned int rows;
unsigned int cols;
public:
Matrix(unsigned int rows, unsigned int cols, unsigned int args_ctr,...): rows(rows),cols(cols){
//react to false input
//--------------------------------------------------------------------------------------------
if(cols * rows < args_ctr){ //to many args
std::cout << "Matrix initilization with to many arguments" << std::endl;
exit(EXIT_FAILURE);
}
//--------------------------------------------------------------------------------------------
arr_ptr = new T[rows*cols];
va_list args;
unsigned int fill_var = 0;
va_start(args,args_ctr);
while (fill_var < args_ctr)
{
arr_ptr[fill_var] = va_arg(args,T);
fill_var++;
}
va_end(args);
}
void print_console(){for(unsigned int i = 0; i < rows*cols; i++){std::cout << arr_ptr[i] << std::endl;}}
};
#endif
Im going to do this with variable Template arguments but why is that error in the conversion?
The problem is that C-style variadic arguments give you absolutely no type safety.
(double)23,23,0
passes a double
and two int
s, and you expect three double
s in the constructor.
You should generally stay away from C-style variadics in C++.
std::initializer_list
Matrix(unsigned int rows, unsigned int cols, std::initializer_list<T> args)
: rows(rows), cols(cols) {
// args.size() can be used to obtain the number of arguments
}
In almost all cases, you know the size of a matrix at compile time anyway. A lot of issues becomes trivial to solve if you turn the rows and columns into non-type template parameters:
template <typename T, std::size_t Rows, std::size_t Columns = Rows>
class Matrix {
private:
// ...
public:
T data[Rows * Columns];
};
You don't even need a constructor anymore, and could write:
using Mat3f = Matrix<float, 3>; // convenience alias
Mat3f mat{/* ... */}; // aggregate initialization, no constructor needed
If you insisted on having a constructor, it could be a constructor taking just one parameter of type std::initializer_list<T>
, and you could still use the syntax Mat3f{...}
.