Make initialization variables accessible to several attributes initialization methods - c++

I write a class using sparse matrices. It happens that for both of them, their non-zeros are on the same (i,j)s. As I have to compute these (i,j)s, I'd prefer to have to do it only once.
Currently, I do it separately and my constructor looks like this:
class C
{
private:
matrix matA;
matrix matA;
holder ijs;
private:
matrix initMatA();
matrix initMatA();
holder init_ijs(int, int);
public:
C(int, int);
};
C::C(int foo, int bar) : init_ijs(foo, bar), matA(initMatA()), matB(initMatB())
{
}
as I've read that it is best practice to use initialization list (and actually, when I first wrote it, if I remember correctly it was impossible to instantiate my matrices otherwise (EDIT: a default constructor seems to fix it?)).
If it was Python, I could write something like
def initMats(foo, bar):
...
return matA, matB
If think the C++ way would be something like
void initMats(int foo, int bar, matrix &matA, matrix &matB)
{
...
}
but I guess I cannot pass reference to objects that have not yet been constructed.
Any clue on a way to solve this? My idea was to first create the (i,j)s list as an attribute to my class so I can later use it in my initA and initB methods, but I will not be needing it afterward I don't think it's the best way to do.

Init methods are not idiomatic in C++. Use constructors.
You can achieve what you want with a delegating constructor (C++11 and newer). First, you need a constructor for the matrix class that accepts an (i,j)-list.
using ijlist = ...; //probably some kind of an array
class matrix {
...
matrix(const ijlist& ijs) { ... }
...
};
Then you write a constructor for C that accepts an ijlist and passes it to the two matrix data members:
class C {
...
matrix matA, matB;
...
C(const ijlist& ijs) : matA(ijs), matB(ijs) { ... }
Now you can compute your (i,j)-list in an auxiliary function and pass it to this constructor from any other constructor:
C() : C(compute_ijs()) { ... }

If I understand the question correctly, you wish to:
take two sparse matricies (or similar) as inputs
compute IJ for the two matricies
apply IJ to them both before continuing
construct the Class with the modified matricies.
The constraint is that the matricies are not default-constructible.
I think I would do it something like this:
// A class to hold the result of computing ij
struct ij_holder
{
// whatever goes here
};
// a sparse matrix class
struct sparse_matrix
{
// let's say it's not default-constructible
sparse_matrix(int, int , int , int);
};
// apply ij to sparse matrix m, returning the modified matrix
sparse_matrix apply(ij_holder const& ij, sparse_matrix m)
{
// whatever goes here to modify m
return m;
}
// compute ij from two matricies
ij_holder compute_ij(sparse_matrix const& a, sparse_matrix const& b);
struct Class
{
// public constructor written in terms of private constructor
Class(sparse_matrix const& foo, sparse_matrix const& bar)
: Class (compute_ij(foo, bar), foo, bar)
{}
private:
// private constructor
Class(ij_holder ij, sparse_matrix const& foo, sparse_matrix const& bar)
: foo_(apply(ij, foo))
, bar_(apply(ij, bar))
{}
sparse_matrix foo_;
sparse_matrix bar_;
};

Related

2D Std::vector of a given class

I'm trying to use a vector to store x and y coordinates of certain data in my vector. I assumed the following would work but that is not the case. I have spent a lot of time searching hoping to get it to work but in vain. I appreciate any help whatsoever.
class A {
public:
A(size_t x, size_t y); //ctor
};
If I want to create a vector of type class A, so 2D, why is
std::vector<A> vec(10); not working?
void count(size_t x, size_t y) {
vec.at(x,y);
}
ERROR: error: no matching function for call to ‘std::vector<Board>::at(size_t, size_t&)
note: candidate expects 1 argument, 2 provided
Since class A's constructor has 2 variables, shouldn#t my vector of type A take 2 variables as well?
If not, what is the correct way of getting a 2d vector of class A such that I can call the .at()-function at x,y and get whatever is stored there?
This vector overload:
std::vector<A> vec(10);
makes 10 copies of type A by calling A's default constructor. Since you didn't provide a default constructor an error occurs. Provide the default constructor:
class A {
public:
A() = default;
};
int main() {
std::vector<A> v(10);
}
or use an appropriate constructor as a second parameter:
class A {
public:
A(size_t x, size_t y) {
// your code
}
};
int main() {
std::vector<A> v(10, A(1, 2));
}
That being said, don't confuse the vector of vectors:
std::vector<std::vector<T>> v;
with a simple constructor taking two parameters or a simple class having two data members.

How to distinguish two overloaded functions with arguments of non-nested and nested initializer_list?

Suppose I have a Matrix class and I'd like to initialize my Matrix objects in two ways:
Matrix a = {1,2,3} // for a row vector
and
Matrix b = {{1,2,3},{4,5,6},{7,8,9}} // for a matrix
As a result, I implemented two copy constructors as below
class Matrix {
private:
size_t rows, cols;
double* mat;
public:
Matrix() {}
Matrix(initializer_list<double> row_vector) { ... }
Matrix(initializer_list< initializer_list<double> > matrix) { ... }
...
}
No matter how I change my interface, such as adding an explicit keyword or change the nested version to Matrix(initializer_list< vector<double> > matrix). It will always cause ambiguities between these two cases:
Matrix a = {1,2,3};n
Matrix b = {{1}, {2}, {3}};
I'm not quite familiar with the stuff like direct/copy initialization or implicit type conversion. Are there any solutions for this problem?
There is no solution which will unambiguously work in every case. However, you can create ways to disambiguate cases:
template<typename T>
auto il(std::initializer_list<T> the_il) -> std::initializer_list<T> { return the_il; }
Matrix b = {il({1}), {2}, {3}};
However, I would personally suggest that you be explicit about it. If a user wants a matrix containing one row, then it should look like a matrix containing one row, not like a vector:
Matrix a = {{1,2,3}};
So I would suggest ditching the first overload altogether.
Well, here's a very dirty trick:
#include <iostream>
#include <initializer_list>
struct Matrix
{
template<class = void> Matrix(std::initializer_list<double>) { std::cout << "vector\n"; }
Matrix(std::initializer_list<std::initializer_list<double>>) { std::cout << "matrix\n"; }
};
int main()
{
Matrix a = {1, 2, 3};
Matrix b = {{1}, {2}, {3}};
(void)a; (void)b;
}
The two overloads cannot be distinguished based on conversions, so we rely on a subsequent step in the overload resolution process: a non-template function is preferred over a template specialization.
Why not just create one constructor that takes a matrix, create a private function copy and inside copy you check for a row_vector.
private void Matrix::copy(const Matrix &matrix)
{
if (matrix.rows == 1)
{
//row vector stuff here
}
else if (matrix.cols == 1)
{
//col vector stuff here
}
else
{
//matrix stuff here
}
}

cannot convert parameter 1 from 'std::_Vector_iterator<_Myvec>' to 'std::_Vector_iterator<_Myvec>'

I have a question, its a bit hard to discribe it so be easy on me please.
I have two classes, A and B, class A have a private member- vector:
class A
{
private:
struct complex
{
int x;
vector< int > y;
};
vector< complex > m_resultVector; // <---- the private member
public:
void getPointerToVector( vector< complex >::iterator it )
{
it = m_resultVector.begin();
}
};
I need to get access (only read) from class B, to this m_resultVector;, I could write a get function but m_resultVector is very long vector and I don't want to copy the entire vector to a new one, I want to send its pointer. also the important part- I need class B cannot change the content of m_resultVector
class B
{
struct complex
{
int x;
vector< int > y;
};
void functionOf_B()
{
A class_A;
vector< complex >::iterator p_resultVector;
class_A.getPointerToVector(p_resultVector); // <------ compilation error here
// some reading from the content of p_resultVector
}
};
when I try to compile it, I get the error:
cannot convert parameter 1 from 'std::_Vector_iterator<_Myvec>' to
'std::_Vector_iterator<_Myvec>'
so basically, I have to questions-
why do I get this error? the complex struct is defined in both classes.
where and how do I need to declare on const iterator on class B, so it will be read only? I'm not sure ...
That is because A::complex and B::complex are different types (with same content, but that does not matter). So that vector<A::complex> and vector<B::complex> are different. Move definition of struct complex outside A and B.
Also there are more issues in your code. A::getPointerToVector does nothing, because it copies input vector iterator to temporary one, assigns a value to it and after return from that function, everything is lost. Using this approach, you would have to pass vector<complex>::iterator as reference (thus vector<complex>::iterator&).
I would rather write a method in A like this
const vector<complex>& get_vector() const
{
return m_resultVector;
}
I this way, you can doo this.
void foo()
{
A class_A;
// do something with A
const vector<complex>& p_result = class_A.get_vector();
// now you are holding whole vector and you can call methods
// defined as const (which does not modify that vector)
p_result.begin();
p_result.at(0);
p_result.end();
}
Zereges solution seems good. But I understand you do not want to return vector. I could not come up with any solution other than below.
In Class A:
void getPointerToVector(int position, int &var,vector<int>& o_Vec)
{
vector<complex>::iterator itr;
complex c;
c = m_resultVector.at(position);
var = c.x;
o_Vec = c.y;
}
In class B :
void functionOf_B()
{
A class_A;
int aVar;
std::vector<int> vec;
class_A.getPointerToVector(2, aVar, vec);
// some reading from the content of p_resultVector
}
I am not sure how efficient and complex this is. I would suggest better to use Zereges solution

performing function with classes of similar type C++

I want to implement a representation of matrices.
for that I have two types of matrices - regular and sparse, which differ in their
implementation - one holds a vector, and the second a map of indices and value,
both inherit from Matrix class.
I want to implement the + operator, which operates on Matrix and receives another Matrix.
but when I implement the + operator, I might receive as parameter sparse/regular matrix.
is there any way to receive a matrix, which I don't know what type of the 2 it is,
and perform the + operator?
meaning, if in class SparseMatrix I receive sparse/regular matrix, how can I implement the operator such that no matter which of the two types I get, it will work?
Matrix & operator+ (Matrix other)
{
...
}
I would probably implement two versions of operator+, and let them call a helper template method:
template <typename ITER>
Matrix add (ITER other_it) {
//...
}
Matrix operator+ (RegularMatrix other)
{
return add(other.begin());
}
Matrix operator+ (SparseMatrix other)
{
return add(other.begin());
}
You could make operator+ a template, but this way makes sure you only allow those Matrix types.
As was pointed out to me, you should not return a reference from +, as the result needs to be point to an instance that exists after the operation returns.
We can use polymorphism to create different implementations of a Matrix. Through the common interface of Matrix, each implementation can interact.
class Matrix
{
class iterator { ... }
friend Matrix operator+(const Matrix &lhs, const Matrix &rhs)
{
// iterate, add, and return new matrix
}
};
class SpareMatrix : public Matrix
{
iterator begin() { ... }
};
class Matrix
{
public:
virtual ~Matrix() {}
virtual Matrix& operator+(Matrix& other) = 0;
};
class MatrixSparse : public Matrix
{
public:
virtual ~MatrixSparse() {}
virtual Matrix& operator+(Matrix& other)
{
MatrixSparse* sparse = dynamic_cast<MatrixSparse*>(&other);
// TODO
}
};
class MatrixRegular : public Matrix
{
public:
virtual ~MatrixRegular() {}
virtual Matrix& operator+(Matrix& other)
{
MatrixRegular* regular = dynamic_cast<MatrixRegular*>(&other);
// TODO
}
};
Also, here is another SO thread dealing with the problem of overloading operators from abstract classes.

Dynamic data type choosing based on template

suppose I have an object like this:
class Spline {
public:
Spline(std::size_t const dim);
// Quite a few functions here. One of those:
vec operator()(double const t) const; // Returns vector of dimension d
}
Now, at most uses of this class, the dimension will already be determined at compile time, thus it would be a good idea (for performance reasons) to change the class like this:
template <std::size_t dim>
class Spline {
public:
Spline();
// Quite a few functions here. One of those:
vec::fixed<dim> operator()(double const t) const; // Returns vector of dimension d
}
(For those who wonder, vec and vec::fixed are objects defined by the armadillo linear algebra library). Now I would like to have both versions living in parallel, thus being able to choose the dimension at compile time as well as during runtime. In short, I would like to create the equivalent of vec::fixed<dim> as Spline::fixed<dim>, but without implementing all functions twice. Especially, I would have to choose the return type of all those functions depending on whether there is a template argument present or not.
Do you have any idea how I might accomplish this, especially thinking in terms of a clear and maintainable design? (In the hope that I made myself clear, which I am not totally sure about.)
Use a simple traits metastruct and specialize that.
template<std::size_t dim>
struct spline_return_traits{
typedef vec::fixed<dim> type;
};
template<>
struct spline_return_traits<0>{ // 0 is a special marker for runtime dimensions
typedef vec type;
};
template<std::size_t dim>
class Spline_impl{
typedef typename spline_return_traits<dim>::type spline_return;
public:
spline_return operator()(double const t) const;
// if <dim> is 0, then the dynamic vec will be chosen as the return type
// all your functions
};
class Spline : public Spline_impl<0>{ // default is dynamic
public:
template<int dim>
struct fixed : public Spline_impl<dim>{
};
};
Now you simple use that. :) Every operator, constructor and function of Spline_impl should be available in the subclasses. For the implementation of each function, you need to do some branching where it's a must to decide between runtime or fixed vec:
if(dim == 0){
// runtime specific stuff
}else{
// compile-time specific stuff
}
Use as:
Spline dynamic_spline;
Spline::fixed<10> fixed_10_spline;
Only problem being that the Spline class will be double the size of Spline_impl... :/ Lemme think if I can find a solution to that too.
Edit: If you don't want Spline to be double the size of Spline_impl, one possibility is to add a little verbosity and a typedef:
class Spline : public Spline_impl<0>{ // default is dynamic size
public:
template<std::size_t dim>
struct fixed{
typedef Spline_impl<dim> type;
};
};
And use as
Spline dynamic_spline;
typename Spline::fixed<10>::type fixed_10_spline;
If I understand your question correctly, you want a struct for compile time usage and runtime usage as well with preferably same name. In my opinion, you can declare the class as template and then specialize one of its instance (say size_t = 0xffffffff), which you may not be using. You can declare all your definitions for runtime usage in that instance.
For example,
template<std::size_t dim = ~0> // choose default dimension(0xffffffff) not to be used
class Spline {
public:
Spline () {}
vec::fixed<dim> operator () (double const t) const {}
};
template<>
class Spline<~0> { // specialize the default dimension for runtime use
public:
Spline (std::size_t const dim) {}
vec operator () (double const t) const {}
};
It can be used as below:
Spline<5> o5; // compile time dimensions
Spline<> o0(3); // run time dimensions (don't mention anything in template)
You can just overload it. Making a non-duplicate implementation, however, is a problem with no generic solution, unless you have more template magic that can do this.