0

So i'm trying to create a vec class that I can do vec math on at a later point.

Was working great until I began Implementing actual procedures on it.

Class vecn:

#include <vector>

template <typename T>
class vecn
{
public:
    vecn() {    }
    template <typename... Args>
    vecn(Args&&... args)
    {
        addtovector(args...);
    }

    friend std::ostream& operator<<(std::ostream& os, const vecn<T>& obj)
    {
        os << "{";
        for (auto it = obj.contents.begin(); it < obj.contents.end(); it++) {
            os << *it;
            if (it != obj.contents.end() -1)
            {
                os << ",";
            }
        }
        os << "}";
        return os;
    }

    template<typename T>
    vecn<T>& operator=(const vecn<T>& v) {
        contents = v.contents;
        return *this;
    }

    unsigned int size() const
    {
        return contents.size();
    }

    vecn<T> operator+(const vecn<T>& v1) {
        vecn<T> v2();
        for (unsigned int i = 0; i < size();i++)
        {
            v2[i] = v1[i] + this->contents[i];
        }
        return v2;
    }

    T& operator[](size_t Index)
    { 
        if (Index > contents.size() -1)
        {
            contents.resize(Index + 1);
        }
        return contents.at(Index);
    }

    const T& operator[](size_t Index) const
    {
        return contents.at(Index);
    }

private:
    template <typename... Args>
    void addtovector(T& first, Args&&... args)
    {
        addtovector(first);
        addtovector(args...);
    }

    void addtovector(T& item)
    {
        contents.push_back(item);
    }
    std::vector<T> contents;
};

Now i'm having a problem with acceing the underling vector using the subscript operator, no matter how I design it, it never quite works. Usually resulting in a

Error   C2109   subscript requires array or pointer type

From Googling the error, I'm supposed to return a pointer to the array with the subscript. which I do.

Is there something i'm missing?

main:

vecn<int> v(1,2);
vecn<int> b(3, 4, 5);
std::cout << v + b;

Expected output:

{4,6,5}
Steven Venham
  • 600
  • 1
  • 3
  • 18

3 Answers3

0

GCC told me exactly what's wrong:

error: declaration of template parameter ‘T’ shadows template parameter

(for your assignment operator)

Then:

warning: pointer to a function used in arithmetic [-Wpointer-arith]
         v2[i] = v1[i] + this->contents[i];

(you've declared v2 as a function returning vecn<T>, remove the parentheses)

Lastly, fix your operator+, because it will try to access elements of an empty v2 vector and access out of range of the smaller of v1 and this->contents if their sizes are not equal.


It seems to me that you have wrote a lot of unnecessary code for such a simple thing. You don't need addtovector, just expand the parameter pack like:

contents{std::forward<Args>(args)...}

in the member initializer list. You don't need to define operator= at all, leave it up to the compiler. And try to implement operator+ in terms of operator+=.

LogicStuff
  • 19,397
  • 6
  • 54
  • 74
0

Despite all other things you have one rather creepy thing in your code

if (Index > contents.size() -1)

You should never ever replace the correct choice of the boolean operator by arithmetic operations! std::vector<>.size() returns size_t (unsigned long on most systems), only your selfmade size() returns int, which it shouldn´t since there is no meaning in negative sizes.

Now 0 - 1 doesn´t yield a negative with 0 being size_t but something huuuge: 18446744073709551615 (0xffffffffffffffff).

So with size()=0

if (Index > contents.size() -1)

Will never ever be true and your vec will not grow, as you wanted, on access to vec[0]. Simply use

if (Index >= contents.size())

Which is exactly what you mean.

DrSvanHay
  • 1,170
  • 6
  • 16
0

Likely your problem was that you used vecn<T> v2(); instead of vecn<T> v2;, but there are another bad things in your solution. Here is some refactor:

template <typename T>
class vecn {
public:
    vecn() {}
    template <typename... Args>
    vecn(Args&&... args)
    {
        addToVector(args...);
    }

    friend std::ostream& operator<<(std::ostream& os, const vecn<T>& obj)
    {
        os << "{";
        for (auto it = obj.contents.begin(); it < obj.contents.end(); it++) {
            os << *it;
            if (it != obj.contents.end() - 1)
                os << ",";
        }
        os << "}";
        return os;
    }

    // you don't need this
    // template<typename T>

    // also whole method is unnecessary
    //    vecn<T>& operator=(const vecn<T>& v)
    //    {
    //        contents = v.contents;
    //        return *this;
    //    }

    // use size_t
    /*unsigned int*/ size_t size() const
    {
        return contents.size();
    }

    vecn<T> operator+(const vecn<T>& other) const
    {
        vecn<T> result;
        size_t resultSize = std::max(other.size(), size());
        result.contents.reserve(resultSize);

        for (size_t i = 0; i < resultSize; ++i) {
            T value = {};
            if (i < other.size())
                value += other.contents[i];
            if (i < size())
                value += contents[i];

            result.contents.push_back(value);
        }

        return result;
    }

    T& operator[](size_t index)
    {
        return contents.at(index);
    }

    const T& operator[](size_t index) const
    {
        return contents.at(index);
    }

private:
    template <typename... Args>
    void addToVector(T& first, Args&&... args)
    {
        addToVector(first);
        addToVector(args...);
    }

    void addToVector(T& item)
    {
        contents.push_back(item);
    }
    std::vector<T> contents;
};
devalone
  • 535
  • 6
  • 21