I'm currently working on a project with several classes :
an abstract one : template <typename Elem> class Vector {...}
another abstract one : template <typename Elem> class AbsPolynom: virtual public Vector<Elem>
a inheritence from Vector : template <typename Elem> class Dvector: virtual public Vector<Elem>
and the last one : template <typename Elem> class Polynom: public AbsPolynom<Elem>, public Dvector<Elem>{
When I call Polynom, like this : Polynom<int> test(std::size_t(3),3,3);
I get this error :
In file included from Polynom.cpp:6:0,
from main2.cpp:4:
Polynom.hpp: In instantiation of ‘Polynom::Polynom(std::size_t, const Elem&, const int&) [with Elem = int; std::size_t = long unsigned int]’:
main2.cpp:10:41: required from here
Polynom.hpp:14:105: error: no matching function for call to ‘Vector::Vector()’
Polynom(std::size_t dim, const Elem& value, const int& degrees ): AbsPolynom(dim, value, degrees) {};
So here is my question : Why does it call this constructor from Vector? I always have a parameter but it initializes this class without parameters
Here are my Constructors :
Polynom :
Polynom(std::size_t dim, const Elem& value, const int& degrees ): AbsPolynom<Elem>(dim, value, degrees) {};
Polynom(std::size_t dim, const Elem& value, const int degrees[] ): AbsPolynom<Elem>(dim, value, degrees) {};
Polynom(std::size_t dim, const Elem values[], const int& degrees): AbsPolynom<Elem>(dim, values, degrees) {};
Polynom(std::size_t dim, const Elem values[], const int degrees[]): AbsPolynom<Elem>(dim, values, degrees) {};
AbsPolynom :
explicit AbsPolynom(std::size_t, const Elem&, const int& );
explicit AbsPolynom(std::size_t, const Elem&, const int [] );
explicit AbsPolynom(std::size_t, const Elem [], const int& );
explicit AbsPolynom(std::size_t, const Elem [], const int [] );
template <typename Elem>AbsPolynom<Elem>::AbsPolynom(std::size_t dim, const Elem& value, const int& degrees ): Vector<Elem>(dim, value), _degrees(new Elem[dim]),_polynomDegree(degrees) {
for (std::size_t i = 0; i < dim; ++i) _degrees[i] = degrees;}
template <typename Elem>AbsPolynom<Elem>::AbsPolynom(std::size_t dim, const Elem& value, const int degrees[] ): Vector<Elem>(dim, value), _degrees(new Elem[dim]),_polynomDegree(degrees[0]) {
for (std::size_t i = 0; i < dim; ++i) _degrees[i] = degrees[i];}
template <typename Elem>AbsPolynom<Elem>:: AbsPolynom(std::size_t dim, const Elem values[], const int& degrees): Vector<Elem>(dim, values), _degrees(new Elem[dim]),_polynomDegree(degrees) {
for (std::size_t i = 0; i < dim; ++i) _degrees[i] = degrees;}
template <typename Elem>AbsPolynom<Elem>::AbsPolynom(std::size_t dim, const Elem values[], const int degrees[]): Vector<Elem>(dim, values), _degrees(new Elem[dim]),_polynomDegree(degrees[0]) {
for (std::size_t i = 0; i < dim; ++i) _degrees[i] = degrees[i];}
and Vector :
explicit Vector(std::size_t dim, const Elem& elem);
explicit Vector(std::size_t, const Elem[] );
template <typename Elem>Vector<Elem>::Vector (std::size_t dim, const Elem& elem):_dim(dim), _values(new Elem[dim]) {
for (std::size_t i = 0; i < dim; ++i) _values[i] = elem; }
template <typename Elem>Vector<Elem>::Vector ( std::size_t dim, const Elem elem[]):_dim(dim), _values(new Elem[dim]) {
for (std::size_t i = 0; i < dim; ++i) _values[i] = elem[i];
}
When you have virtual inheritance, the most derived class has to call the constructor for the virtual base class. There is only one copy, and it has to be called exactly once.
If not called, the compiler tries to call the default constructor (and fails if there is none).
Related
Original context:
I am trying to pass a tuple of (object, expected_value_of_some_property) to a test function
I created a simple class to reproduce the error I am facing:
template <typename T>
class Vector
{
private:
size_t m_size;
std::unique_ptr<std::vector<int>> m_vector;
public:
Vector();
Vector(const Vector<int>&);
~Vector() = default;
void push_back(T);
T get(int) const;
size_t size() const;
};
template <typename T>
Vector<T>::Vector()
:m_size(0),
m_vector(new std::vector<T>)
{}
template <typename T>
Vector<T>::Vector(const Vector<int>& v)
:m_size(v.size()),
m_vector(new std::vector<T>)
{
for (size_t i = 0; i < v.size(); i++)
{
this->push_back(v.get(i));
}
}
template <typename T>
void Vector<T>::push_back(T value)
{
m_vector->push_back(value);
m_size ++;
}
template <typename T>
T Vector<T>::get(int index) const
{
return m_vector->operator[](index);
}
template <typename T>
size_t Vector<T>::size() const
{
return m_size;
}
The error is triggered when trying to produce a tuple of Vector object and an int somewhere in a test code:
int main(int argc, char const *argv[])
{
std::tuple<Vector<int>, int> vector_test;
vector_test = std::make_tuple(Vector<int>{}, 0);
int size = std::get<0>(vector_test);
Vector<int> vector = std::get<1>(vector_test);
// .. test code
return 0;
}
Output:
error: use of deleted function ‘std::tuple<Vector<int>, int>& std::tuple<Vector<int>, int>::operator=(const std::tuple<Vector<int>, int>&)’
20 | vector_test = std::make_tuple(Vector<int>{}, 0);
| ^ ^
What am I doing wrong here?
Since your Vector class has a unique_ptr member, that means your class itself has the copy-assignment implicitly deleted. Therefore this assignment will fail
std::tuple<Vector<int>, int> vector_test;
vector_test = std::make_tuple(Vector<int>{}, 0); // <--- this
Instead you can just directly initialize in one step
std::tuple<Vector<int>, int> vector_test = std::make_tuple(Vector<int>{}, 0);
I have problem with implicit conversions in C++.
I'm trying to create some Expression template for vector arithmetics (I know that same libraries already exists. I'm just learning C++ so I wanted to try something with templates).
I would like to create class Vector, that is able to compute like this:
simd::test::Vector<char, 5> a;
simd::test::Vector<short, 5> b;
auto ret = a + b + a + b;
, where on output would be Vector of shorts becouse short is bigger type than char.
Right now, I have class that is able to adds vectors of same data types. For different types I have to call explicit conversion:
//simd::test::Vector<short, 5>(a)
auto ret = simd::test::Vector<short, 5>(a) + b + simd::test::Vector<short, 5>(a) + b;
Is possible to implicit convert Vector before pass into function "operator+()"? Here is my code of Vector:
#pragma once
#include <type_traits>
namespace simd {
namespace test {
template<typename R, std::size_t Dim,
typename std::enable_if<std::is_arithmetic<R>::value>::type* = nullptr
>
class Vector_expression {
public:
static constexpr std::size_t size = Dim;
virtual const R operator[] (std::size_t index) const = 0;
virtual ~Vector_expression() = default;
};
template<typename T, std::size_t Dim>
class Vector final : public Vector_expression<T, Dim> {
private:
T data[Dim];
public:
Vector() = default;
template<typename R>
Vector(const Vector_expression<R, Dim> &obj) {
for(std::size_t index = 0; index < Dim; ++index) {
data[index] = obj[index];
}
}
template<typename R>
Vector(Vector_expression<R, Dim> &&obj) {
for(std::size_t index = 0; index < Dim; ++index) {
data[index] = obj[index];
}
}
template<typename R>
Vector<T, Dim> & operator=(const Vector_expression<R, Dim> &obj) {
for(std::size_t index = 0; index < Dim; ++index) {
data[index] = obj[index];
}
return (*this);
}
template<typename R>
Vector<T, Dim> & operator=(Vector_expression<R, Dim> && obj) {
for(std::size_t index = 0; index < Dim; ++index) {
data[index] = obj[index];
}
return (*this);
}
virtual const T operator[] (std::size_t index) const override {
return data[index];
}
T & operator[] (std::size_t index) {
return data[index];
}
virtual ~Vector() = default;
};
template<typename E1, typename E2, typename R, std::size_t Dim>
class Vector_sum final : public Vector_expression<R, Dim> {
private:
const E1 & _lhs;
const E2 & _rhs;
public:
Vector_sum() = delete;
Vector_sum(const E1 & lhs, const E2 & rhs) :
_lhs(lhs),
_rhs(rhs)
{}
virtual const R operator[] (std::size_t index) const override {
return _lhs[index] + _rhs[index];
}
virtual ~Vector_sum() = default;
};
template<typename R, std::size_t Dim>
Vector_sum<Vector_expression<R, Dim>, Vector_expression<R, Dim>, R, Dim> operator+ (const Vector_expression<R, Dim> & lhs, const Vector_expression<R, Dim> & rhs) {
return {lhs, rhs};
}
}
}
Just define an operator+ that allows different argument types. The one catch is determining the element type of the resulting sum. Probably the best option is to use whatever the result of adding two elements is. One way to write this type is:
decltype(std::declval<const R1>() + std::declval<const R2>())
Or if you know the types are built-in arithmetic types, that would be the same as
std::common_type_t<R1, R2>
Or using a trailing return type, we can take advantage of the function parameters to shorten the std::declval expressions:
template<typename R1, typename R2, std::size_t Dim>
auto operator+ (const Vector_expression<R1, Dim> & lhs,
const Vector_expression<R2, Dim> & rhs)
-> Vector_sum<Vector_expression<R1, Dim>, Vector_expression<R2, Dim>,
decltype(lhs[0] + rhs[0]), Dim>
{
return {lhs, rhs};
}
It could be done using templates and std::common_type, something like this:
template<typename T1, typename T2, size_t S>
simd::test::Vector<typename std::common_type<T1, T2>::type, S>
operator+(simd::test::Vector<T1, S> const& v1,
simd::test::Vector<T2, S> const& v2)
{
// TODO: Implementation...
}
I have a template class hierarchy , I have to derived a class from an abstract one that declare :
template<typename T>
virtual T findValue(const std::size_t , const std::size_t ) const noexcept = 0;
But in the derived class my findValue method have different signature :
template<typename T>
T findValue(const std::size_t i, const std::size_t j,
const std::size_t rBlock, const std::size_t cBlock
) const noexcept ;
So what is the best way to make the derived class not abstract ?
of course I can define :
private:
template<typename T>
T findValue(const std::size_t r, const std::size_t c) const noexcept override
{ return T(0) ; }
but I don't like this ! so what are better ways to doing so and working with derived class (not abstract of course)
EDIT
in all the function above the template <> is referred to the class not to the method :
template <typename T>
class BlockCompressedMatrix :
public SparseMatrix<T>
{
public:
virtual T& operator()(const std::size_t , const std::size_t) noexcept override = 0 ;
virtual const T& operator()(const std::size_t , const std::size_t) const noexcept override = 0 ;
virtual void print() const noexcept override = 0;
protected:
virtual std::size_t findBlockIndex(const std::size_t, const std::size_t ) const noexcept = 0 ;
virtual T findValue(const std::size_t , const std::size_t ) const noexcept = 0;
};
and the derived is something like this ! (this compile)
# include "BlockCompressedMatrix.H"
namespace mg {
namespace numeric {
namespace algebra {
template <typename T>
class Block
: public BlockCompressedMatrix<T>
{
public:
Block(const std::size_t n)
{
ba_.resize(n);
}
T& operator()(const std::size_t , const std::size_t ) noexcept override ;
const T& operator()(const std::size_t , const std::size_t )const noexcept override ;
void constexpr print() const noexcept override ;
private:
using SparseMatrix<T>::dummy ;
std::vector<T> ba_ ;
std::size_t findBlockIndex(const std::size_t , const std::size_t ) const noexcept override {return 0;} ;
T findValue(const std::size_t , const std::size_t ) const noexcept override {return T(0);} ;
};
template <typename T>
T& Block<T>::operator()(const std::size_t i, const std::size_t j) noexcept {
dummy = ba_[0];
return dummy ;
}
template <typename T>
const T& Block<T>::operator()(const std::size_t i, const std::size_t j)const noexcept {
dummy = ba_[0];
return dummy ;
}
template <typename T>
void constexpr Block<T>::print() const noexcept
{
std::cout << "Hello !" << std::endl;
}
I'm having some problem with my std::forward constructor for my template "matrix" class. Basically i want to set a matrix of type float and size 4 equal to the sum of 2 matrices of type float and size 3. I do this inside of my struct 'matrix_struct' in the function 'test'. However, MSVC error tells me that "'static_cast': cannot convert from 'matrix' to 'float'" and whenever I inspect the error it takes me to the 3rd matrix constructor with std::forward.
///////////////////////////////////
somefile.hpp
#pragma once
#include "matrix.hpp"
using matrix3 = matrix<float, 3>;
using matrix4 = matrix<float, 4>;
struct matrix_struct {
matrix4 sum;
void test(const matrix3& a, const matrix3& b)
{
sum = a + b;
}
}
///////////////////////////////////
matrix.hpp
#pragma once
#include <array>
template <typename t, size_t dim>
class matrix
{
public:
matrix() { data.fill(static_cast<t>(0) }
explicit matrix(const std::array<t, dim>& a) : data(a) {}
template <typename... args_t>
matrix(args_t... args) : data{ static_cast<t>(std::forward<args_t>(args))... } }
public:
t& at(const size_t index)
{
return data.at(index >= dim ? dim - 1 : index);
}
const t& at(const size_t index) const
{
return data.at(index >= dim ? dim - 1 : index);
}
public:
matrix& operator = (const matrix<t, dim>& other)
{
for (size_t i = 0; i < dim; ++i) {
at(i) = other.at(i);
}
return *this;
}
matrix& operator = (const std::array<t, dim>& other)
{
for (size_t i = 0; i < dim; ++i) {
at(i) = other.at(i);
}
return *this;
}
matrix& operator = (const t& other)
{
for (size_t i = 0; i < dim; ++i) {
at(i) = other;
}
return *this;
}
public:
matrix operator + (const matrix<t, dim>& other) const
{
matrix<t, dim> ret;
for (size_t i = 0; i < dim; ++i) {
ret.at(i) = at(i) + other.at(i);
}
return ret;
}
matrix operator + (const std::array<t, dim>& other) const
{
matrix<t, dim> ret;
for (size_t i = 0; i < dim; ++i) {
ret.at(i) = at(i) + other.at(i);
}
return ret;
}
matrix operator + (const t& other) const
{
matrix<t, dim> ret;
for (size_t i = 0; i < dim; ++i) {
ret.at(i) = at(i) + other;
}
return ret;
}
private:
std::array<t, dim> data;
};
Template constructors are problematic. They often create code that is a better candidate than your other constructors.
The general solution is to disable the template if its decayed type matches the class you are writing.
example:
struct MyClass
{
template
<
class Arg,
class...Rest,
std::enable_if_t
<
! std::is_same
<
std::decay_t<Arg>,
MyClass
>::value
>* = nullptr
>
MyClass(Arg&& arg, Rest&&...rest)
{
// code to construct from something that's not MyClass
// this will no longer hijack copy constructors etc.
}
};
The first problem of your code sample is addressed by #RichardHodges's answer.
Assuming you include his solution to overcome tricky copy/move constructor selection, another problem remains: you do not offer a matrix promotion/demotion service through your constructors/assignment operators.
Therefore, the following line in your test function:
sum = a + b; // a + b is a matrix<float, 3>, sum a matrix<float, 4>
Will trigger a call to the variadic template constructor and fail.
Starting from Richard's solution, you need to tweak a bit the SFINAE condition to extend it to matrices of any size. To do so, we will need a little is_matrix trait:
template <typename T, size_t Dim>
class matrix;
template <typename T>
struct is_matrix : std::false_type {};
template <typename Num, size_t Size>
struct is_matrix<matrix<Num, Size> > : std::true_type {
using value_type = Num;
};
Now the variadic template constructor becomes:
template <typename t, size_t dim>
class matrix
{
/* ... */
public:
/* ... */
template
<
class Arg,
class...Rest,
std::enable_if_t
<
! std::is_matrix
<
std::decay_t<Arg>
>::value
>* = nullptr
>
matrix(Arg&& arg, Rest&&...rest)
{
// code to construct from something that's not a matrix
// this will no longer hijack copy constructors etc.
}
};
Then, we need to add the proper matrix constructor along with the proper friend declaration:
template <typename t, typename dim>
class matrix {
public:
template <typename OtherT, size_t OtherDim>
friend class matrix;
template <size_t OtherDim>
matrix(matrix<t, OtherDim> const& other) {
size_t i = 0;
for (; i < min(OtherDim, dim); ++i) {
data[i] = other.data[i];
}
for(; i < dim; ++i) {
data[i] = t();
}
}
template <typename OtherT,
size_t OtherDim>
matrix(matrix<OtherT, OtherDim> const&) {
static_assert(std::is_same<t, OtherT>::value,
"value_type mismatch between matrices!");
}
/* ... */
};
Note: You need the friend declaration because matrix<Type1, Dim1> and matrix<Type2, Dim2> are completely different types whenever Type1 != Type2 or Dim1 != Dim2 and as such, you cannot access matrix<OtherT, OtherDim>'s private/protected members in matrix<t, dim> without that friend declaration.
This implementation will initialize the target matrix by filling its data member with the content of the given matrix when the value types match:
If the given matrix is bigger, it will be truncated.
If the given matrix is smaller, the remaining elements will be 0 initialized
If the value types don't match, the less specialized matrix<OtherT, OtherDim> constructor is the only available overload and it triggers a compiler error through a static_assert.
You would also need to define the equivalent assigment operators... Which I left as exercises.
A demo of these constructors in action can be found on Coliru
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have a very strange issue when creating an object of the class "CorrelatedNormalGenerator". Please see code below. The class Matrix is used by the class CorrelatedNormalGenerator. Thanks in advance for your help.
in Matrix.h
#include <string>
#include <vector>
using namespace std;
template <typename T, typename I>
class Matrix
{
private:
vector<vector<T> > M;
I minRowIndex, maxRowIndex;
I minColIndex, maxColIndex;
I rowNumber, colNumber;
public:
Matrix(); // default constructor
Matrix(const I& _rowNumber,
const I& _colNumber,
const T& value = 0.0,
const I& _minRowIndex = 0,
const I& _minColIndex = 0);
Matrix<T,I>& operator = (const Matrix<T,I>& N);
Matrix(const Matrix<T,I>& N); // copy constructor,
virtual ~Matrix(){};
T& operator() (const I& row, const I& col);
const T& operator() (const I& row, const I& col) const;
};
template<typename T, typename I>
Matrix<T,I> :: Matrix(const Matrix<T,I>& N)
{
M = N.M;
rowNumber = N.GetRows();
colNumber = N.GetCols();
minRowIndex = N.minRowIndex;
minColIndex = N.minColIndex;
maxRowIndex = N.minRowIndex + N.rowNumber - 1;
maxColIndex = N.minColIndex + N.colNumber - 1;
}
template<typename T, typename I>
Matrix<T,I> :: Matrix( const I& _rowNumber,
const I& _colNumber,
const T& value,
const I& _minRowIndex,
const I& _minColIndex)
{
minRowIndex = _minRowIndex;
minColIndex = _minColIndex;
maxRowIndex = _minRowIndex + _rowNumber - 1;
maxColIndex = _minColIndex + _colNumber - 1;
rowNumber = _rowNumber;
colNumber = _colNumber;
M.resize(rowNumber);
for (I i = minRowIndex ; i < rowNumber; i++)
M[i].resize(colNumber, value);
}
template<typename T, typename I>
T& Matrix<T,I> :: operator() (const I& row, const I& col)
{
return M[row][col];
}
// Access the individual elements (const)
template<typename T, typename I>
const T& Matrix<T,I> :: operator() (const I& row, const I& col) const
{
return M[row][col];
}
template<typename T, typename I>
Matrix<T,I>& Matrix<T,I> :: operator = (const Matrix<T,I>& N)
{
rowNumber = N.GetRows();
colNumber = N.GetCols();
minRowIndex = N.minRowIndex;
minColIndex = N.minColIndex;
maxRowIndex = N.minRowIndex + N.rowNumber - 1;
maxColIndex = N.minColIndex + N.colNumber - 1;
M.resize(rowNumber);
I i,j;
for (i= minRowIndex; i <= maxRowIndex; i++)
{
M[i].resize(colNumber);
}
for (i= minRowIndex; i <= maxRowIndex; i++)
{
for (j = minColIndex; j <= maxColIndex; j++)
{
M[i][j] = N(i,j);
}
}
return *this;
}
in CorrelatedNormalGenerator.h
#include "Matrix.h"
#include <cmath>
using namespace std;
template <typename T, typename I> // I = paramanter of matrix
class CorrelatedNormalGenerator
{
private:
Matrix <T,I> SIGMA; // covariance matrix
public:
CorrelatedNormalGenerator(Matrix <T,I>& _SIGMA);
vector <T> GetCorrVectorSingleAsset(const vector<T>& uncorrVector1,
const vector<T>& uncorrVector2);
vector <T> GetCorrVectorMultiAsset(const vector<T>& uncorrVector);
virtual ~CorrelatedNormalGenerator(){};
};
template <typename T, typename I>
CorrelatedNormalGenerator<T,I> :: CorrelatedNormalGenerator(Matrix <T,I>& _SIGMA)
{
SIGMA =_SIGMA;
}
template <typename T, typename I>
vector <T> CorrelatedNormalGenerator<T,I> :: GetCorrVectorMultiAsset(const vector<T>& uncorrVector)
{
Matrix<T,I> Chol = SIGMA.Cholesky();
return Chol*uncorrVector;
}
template <typename T, typename I>
vector <T> CorrelatedNormalGenerator<T,I> :: GetCorrVectorSingleAsset(const vector<T>& uncorrVector1, const vector<T>& uncorrVector2)
{
vector<T> corrVector(uncorrVector1.size());
for (unsigned i = 0; i < uncorrVector1.size(); i++)
corrVector[i] = rho*uncorrVector1[i] + sqrt(1- rho*rho)*uncorrVector2[i];
return corrVector;
}
in MAIN.cpp
#include "CorrelatedNormalGenerator.h"
using namespace std;
int main()
{
Matrix<double, int> P (3,3,0.0);
P(0,0) = 1.0;
P(1,1) = 1.0;
P(2,2) = 1.0;
P(1,2) = P(2,1) = 0.5;
P(0,1) = P(1,0) = 0.6;
P(0,2) = P(2,0) = 0.3;
CorrelatedNormalGenerator<double, int> gen(P); // ERROR: MAIN.cpp MAIN.obj : error LNK2019: unresolved external symbol "public: __thiscall Matrix<double,int>::Matrix<double,int>(void)" (??0?$Matrix#NH##QAE#XZ) referenced in function "public: __thiscall CorrelatedNormalGenerator<double,int>::CorrelatedNormalGenerator<double,int>(class Matrix<double,int> &)" (??0?$CorrelatedNormalGenerator#NH##QAE#AAV?$Matrix#NH###Z)
return 0;
}
It is telling you that you did not implement the Matrix default constructor, and I don't see it in the code you posted. Add the code for
Matrix<T,I>::Matrix<T,I>()
It is needed because you define a matrix in CorrelatedNormalGenerator without initializing it in an initializer list using one of the other Matrix ctors, hence the need for default ctor :
private:
Matrix <T,I> SIGMA; // covariance matrix