Background
I am self-learning C++ from this course. I am trying to overload an operator in a class using a friend function (Assignment 4.2).
EDIT
The linked question does not answer my question. The accepted solution to that question gives a way for templates to be implemented in header + cpp file (not all in the same file).
In fact, I have consulted that question to partially come up with my situation.
My attempt
Using Approach 2, I have almost gotten my code to work (see the cryptic error message). It turns out I am missing a <>
. (Solution manual).
I have tried googling, but no-one else had the situations of
simultaneously.
My rationale
You should not use a class public function to do operator overloading, because the object who calls the function will be implicitly passed, taking up one function parameter. It is better code-style to have the overloaded operator be symmetric (both in usage and in definition).
The usage of friend
was suggested by the lecture notes.
Question
<>
needed?Thank you.
Code
stack.h
#include <iostream>
#include <vector>
using std::cout;
using std::vector;
template <typename T>
class Stack;
template <typename T>
Stack<T> operator+(Stack<T> a, Stack<T> b);
template <typename T>
class Stack { // use default constructors and destructors
private:
vector<T> s;
public:
bool empty();
void push(const T &item);
T& top();
void pop();
friend Stack<T> operator+(Stack<T> a, Stack<T> b); // need operator+<>
};
stack.cpp
#include <iostream>
#include <vector>
using std::cout;
#include "stack.h"
template <typename T>
bool Stack<T>::empty() {
return s.empty();
}
template <typename T>
void Stack<T>::push(const T &item) {
s.push_back(item);
}
template <typename T>
T& Stack<T>::top() {
return s.back();
}
template <typename T>
void Stack<T>::pop() {
s.pop_back();
}
template <typename T>
Stack<T> operator+(Stack<T> a, Stack<T> b) {
Stack<T> temp;
while (!b.empty()) {
temp.push(b.top());
b.pop();
}
while (!a.empty()) {
temp.push(a.top());
a.pop();
}
Stack<T> c;
while (!temp.empty()) {
c.push(temp.top());
temp.pop();
}
return c;
}
int main() {
Stack<int> a, b;
a.push(1);
a.push(2);
b.push(3);
b.push(4);
Stack<int> c = a + b;
cout << c.top() << "\n";
return 0;
}
Error message
Undefined symbols for architecture x86_64:
"operator+(Stack<int>, Stack<int>)", referenced from:
_main in stack-d2f02a.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1
You need to add <>
(or <T>
) to make the friend declaration referring to the declared operator template. Without that the friend declaration would declare a non-template operator+
which is not defined, that's why you got the linker error.
BTW: You can also specify the template argument explicitly like
// refers to the instantiation of template operator+ for T
friend Stack<T> operator+<T>(Stack<T> a, Stack<T> b);
// ^^^
When using <>
the template parameter T
would be deduced from function parameter, and has the same effect.
// refers to the instantiation of template operator+ for T
// T is deduced from function parameters
friend Stack<T> operator+<>(Stack<T> a, Stack<T> b);
// ^^