1

As an exercise to learn a little more about dynamic memory allocation in C++, I'm working on my own vector class. I'm running into a little difficulty overloading the sum operator, so I thought I'd turn here to get some insight into why this doesn't work. Here's what I have so far:

template<typename T>
class vector
{
private:
    T* pointer_;
    unsigned long size_;
public:
    // Constructors and destructors.
    vector();
    template<typename A> vector(const A&);
    template<typename A> vector(const A&, const T&);
    vector(const vector<T>&);
    ~vector();

    // Methods.
    unsigned long size();
    T* begin();
    T* end();
    vector<T>& push_back(const T&); 

    // Operators.
    T operator[](unsigned long);
    vector<T>& operator=(const vector<T>&);
    friend vector<T>& operator+(const vector<T>&, const vector<T>&);
};

The template<typename A> vector(const A&) constructor looks like this:

template<typename T> template<typename A>
vector<T>::vector(const A& size)
{
    this->pointer_ = new T[size];
    this->size_ = size;
}

Finally, the operator+ operator looks like this:

template<typename T>
vector<T>& operator+(const vector<T>& lhs, const vector<T>& rhs)
{
    vector<T> result(lhs.size_);
    for (unsigned long i = 0; i != result.size_; i++)
    {
        result.pointer_[i] = lhs.pointer_[i] + rhs.pointer_[i];
    }
    return result;
}

My compiler (VS2013) returns an unresolved external symbol error when I try to compile this code, which (as I understand it) means there's a function declared somewhere that I haven't actually defined. I'm not sure where the problem is, however: the template<typename A> vector(const A&) constructor works fine. What am I missing?

Community
  • 1
  • 1
crcvd
  • 1,465
  • 1
  • 12
  • 23
  • 1
    All that code is [in a header file](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file), *right?* – WhozCraig Aug 19 '14 at 00:49
  • Also note that you're returning reference of a local variable 'result'. – jazaman Aug 19 '14 at 00:50
  • You're declaring a non-template `friend` function, but never defining one (you define a template `friend` later on). See [this](http://web.mst.edu/~nmjxv3/articles/templates.html) page for details. Note that gcc will warn about the above with the `-Wall` flag, not sure if VS does the same. – user657267 Aug 19 '14 at 00:53
  • Try replacing `friend vector& operator+(const vector&, const vector&);` with `template friend vector& operator+(const vector&, const vector&);` –  Aug 19 '14 at 00:55
  • Add `vector::` in front of `operator+` in the implementation – OMGtechy Aug 19 '14 at 01:06
  • @OMGtechy I thought `vector::` didn't need to be used in the case of `friend` functions? – crcvd Aug 19 '14 at 01:10
  • I haven't used them too often. Would it not be better to not use `friend` at all and simply take one argument? – OMGtechy Aug 19 '14 at 01:11
  • @OMGtechy you might want to hold back on the advice if you aren't sure, `friend` functions aren't defined with `::` (they aren't members!), and non-member binary operators are preferred over member unary operators because they preserve symmetry, as you can see in the [standard library](http://en.cppreference.com/w/cpp/container/vector/operator_cmp) itself. – user657267 Aug 19 '14 at 01:25

1 Answers1

1

You're not properly friending the template operator function. There are multiple ways to do this, each of which has advantages. One is the friend-the-world ideology where all expansions of the template are friends with each other. I prefer to be a bit more restrictive than that.

Above your vector class, do this:

template<typename T>
class vector;

template<typename T>
vector<T> operator+(const vector<T>& lhs, const vector<T>& rhs);

The proceed as before, but note the syntax in the friend declaration:

// vector class goes here....
template<typename T> class vector
{
    .... stuff ....

   friend vector<T> operator+<>(const vector<T>&, const vector<T>&);
};

Then define the rest as you have it. That should get you what I think you're trying to achieve.

Best of luck.

PS: invalid reference return value fixed in the above code.

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • Thanks--it appears this fixes the problem with the sum operator. To clarify: the function returning a `vector` by value means that whatever I assign the sum to (i.e. `a = b + c`) will simply have its private members (`pointer_` and `size_`) assigned the values held by `result`, correct? Having some difficulties getting that assignment to work (but that's probably a matter for another question later on...) – crcvd Aug 19 '14 at 01:53