user13088490
user13088490

Reputation:

Templated elipsis constructor C++

I want to create a templated math vector class. But it says code editor says ambiguous constructor.

I use only header file!!

.h

template<class T>
class MathVec {
    private:
        std::vector<T> mathVec;
        size_t dimension;
    public:
        MathVec(size_t dim);
        MathVec(size_t dim, ...);
        MathVec(const MathVec& other);
        MathVec();
        void print();

};

template<class T>
MathVec<T>::MathVec(size_t dim) {
    this->dimension = dim;
    this->mathVec = std::vector<T>(dim,0);
}

template<class T>
MathVec<T>::MathVec(size_t dim, ...) {
    this->mathVec = std::vector<T>(dim);
    this->dimension = dim;
    va_list list;
    va_start(list, dim);
    for (size_t i = 0; i < dim; i++){
        this->mathVec[i] = va_arg(list, T);
    }
    va_end(list);
}

template<class T>
MathVec<T>::MathVec(const MathVec & other) {
    this->dimension = other.dimension;
    this->mathVec = other.mathVec;
}

template<class T>
MathVec<T>::MathVec() {
    this->dimension = 0;
}

template<class T>
void MathVec<T>::print() {
    for(int i = 0; i < this->dimension; ++i)
        std::cout << this->mathVec[i] << " ";
    std::cout << std::endl;
}

In the main.cpp file I use the following code it is working.

MathVec<int> vect(3,1,2,3);
vect.print();

But if I use the following code it is not working

MathVec<int> vect(1);
vect.print();

The error message is the following.

main.cpp:9:18: error: call to constructor of 'MathVec<int>' is ambiguous
mathvec.h:14:9: note: candidate constructor
mathvec.h:15:9: note: candidate constructor
mathvec.h:16:9: note: candidate constructor

I assume that wrong with the ellipsis, but I do not know what can be the problem, and how to solve this issue.

Upvotes: 1

Views: 129

Answers (4)

WhiteGoat
WhiteGoat

Reputation: 25

In general I would avoid using C style variadic arguments, check variadic templates instead (C++11) or fold expressions (C++17)

Upvotes: 0

Soonts
Soonts

Reputation: 21936

Modern C++ has better way to accomplish that. Create the following constructor:

MathVec( std::initializer_list<T> values )

Usage:

MathVec<int> vect( { 1, 2, 3 } );

Upvotes: 1

s.b.
s.b.

Reputation: 96

may I offer some improvements to your design? There is no reason to pass dimension as a parameter to constructor. I think be better to make it template parameter. Thus, when you try mix in some expression matrices with different dimensions, you catch error at compile time, not when program executes ;)

Working example:

#include <vector>
#include <iostream>

template <typename T, unsigned int dim>
class Matrix
{
        const unsigned int m_dim = dim;
        std::vector<T> m_vec;
public:
        Matrix(): m_vec(std::vector<T>(m_dim, 0)) {}
        virtual ~Matrix() {}
        //suppose, we want m_vec be R/O for public
        const std::vector<T>& Read() {return m_vec;}
};

int main(int, char **)
{
    Matrix<double, 4> m;
    for (auto& x : m.Read()) 
      std::cout << x << std::endl;
}

Upvotes: 1

Tom Gebel
Tom Gebel

Reputation: 805

My guess would be that the compiler does not know what constructor to call, as these two:

MathVec(size_t dim);
MathVec(size_t dim, ...);

can both be called by

MathVec<int> vect(1);

Upvotes: 1

Related Questions