Problems with template in c++ [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Undefined symbol on a template operator overloading function
Here are my source code.
In Number.h
#ifndef NUMBER_H
#define NUMBER_H
#include <iostream>
using std::istream;
using std::ostream;
template <class T> class Number;
template <class T>
ostream& operator<<(ostream&, const Number<T>&);
template <class T>
istream& operator>>(istream&, Number<T>&);
template <class T>
class Number{
public:
Number(const T &n) :i(n) {}
Number() :i(0) {}
T& operator+(const Number&rhs) const;
T& operator-(const Number&rhs) const;
T& operator*(const Number&rhs) const;
T& operator/(const Number&rhs) const;
friend ostream& operator<< <T> (ostream& , const Number<T>&);
friend istream& operator>> <T> (istream& , Number<T>&);
private:
T i;
};
#endif
And in Number.cpp
#include "Number.h"
template<class T>
T& Number<T>::operator+(const Number&rhs) const
{
return i+rhs.i;
}
template<class T>
T& Number<T>::operator-(const Number&rhs) const
{
return i-rhs.i;
}
template<class T>
T& Number<T>::operator*(const Number&rhs) const
{
return i*rhs.i;
}
template<class T>
T& Number<T>::operator/(const Number&rhs) const
{
return i/rhs.i;
}
template<class T>
ostream& operator<<(ostream&os , const Number<T>&rhs)
{
return os<< rhs.i;
}
template<class T>
istream& operator>>(istream&is , Number<T>&rhs)
{
return is >> rhs.i;
}
I cannot find out why there is
undefined reference to `std::istream& operator>><double>(std::istream&,Number<double>&)'
undefined reference to `Number<double>::operator+(Number<double> const&) const'
errors so on so forth

Use .hpp for template and you can't return reference on a temporary object.
number.h
#ifndef NUMBER_H
#define NUMBER_H
#include <iostream>
using std::istream;
using std::ostream;
template <class T> class Number;
template <class T>
ostream& operator<<(ostream&, const Number<T>&);
template <class T>
istream& operator>>(istream&, Number<T>&);
template <class T>
class Number{
public:
Number(const T &n) :i(n) {}
Number() :i(0) {}
T operator+(const Number&rhs) const; // Error Here return T not T&
T operator-(const Number&rhs) const;
T operator*(const Number&rhs) const;
T operator/(const Number&rhs) const;
friend ostream& operator<< <T> (ostream& , const Number<T>&);
friend istream& operator>> <T> (istream& , Number<T>&);
private:
T i;
};
#include <number.hpp>
#endif
number.hpp
#ifndef NUMBER_HPP
#define NUMBER_HPP
template<class T>
T
Number<T>::operator+(const Number& rhs) const
{
return i + rhs.i;
}
template<class T>
T
Number<T>::operator-(const Number&rhs) const
{
return i-rhs.i;
}
template<class T>
T
Number<T>::operator*(const Number&rhs) const
{
return i*rhs.i;
}
template<class T>
T
Number<T>::operator/(const Number&rhs) const
{
return i/rhs.i;
}
template<class T>
ostream& operator<<(ostream&os , const Number<T>&rhs)
{
return os<< rhs.i;
}
template<class T>
istream& operator>>(istream&is , Number<T>&rhs)
{
return is >> rhs.i;
}
#endif
main.cpp
#include <iostream>
#include <number.h>
int
main(int, const char**)
{
Number<double> value(1);
Number<double> add(3);
std::cout << value + add << std::endl;
std::cout << value * add << std::endl;
std::cout << value - add << std::endl;
std::cout << value / add << std::endl;
return 0;
}

The definitions of all those member functions need to be available to any translation unit that instantiates the template. Imagine a file that includes Number.h and attempts to use Number<int>. The compiler then needs to generate all of the code for Number instantiated with T as int. How can it do that if it's only seen Number.h? It doesn't know the definition of the member functions.
The fix is to put the definitions of your member functions (everything from Number.cpp) in Number.h. Alternatively, some people like to name Number.cpp as Number.tpp and, instead of #include "Number.h" in Number.cpp, put #include "Number.tpp" at the bottom of Number.h - basically inverting the inclusion so that the header always includes the implementation.

Related

How to override output operator (<<) as a function template outside a class template

I am reading Section 2.4 of the book "C++ tempalte, a complete guide".
I tried to override output operator (<<) as a function template outside the class template Stack<>.
Below is my code, but it doesn't work.
#include <iostream>
#include <string>
#include <vector>
template<class T>
class Stack
{
private:
std::vector<T> v;
public:
void push(T a);
void printOn(std::ostream & os) const;
template <typename U>
friend std::ostream& operator<< (std::ostream& out, const Stack<U> & s);
};
template<typename T>
std::ostream& operator<< (std::ostream out, const Stack<T> & s)
{
s.printOn(out);
return out;
}
template<class T>
void Stack<T>::push(T a)
{
v.push_back(a);
}
template<class T>
void Stack<T>::printOn(std::ostream & out) const
{
for(T const & vi : v)
{out << vi << " ";}
}
int main()
{
Stack<int> s1;
s1.push(12);
s1.push(34);
std::cout << s1;
}
You are just omitting the &, which makes the operator<< inside and outside the class have different function signatures, they are both valid for std::cout << s1, hence the ambiguity
template<typename T>
std::ostream& operator<< (std::ostream& out, const Stack<T> & s)
// ^
{
s.printOn(out);
return out;
}

Stack adapted from Deque Pointer?

For my course, I'm asked to create a Stack class that stores its elements in a STL container (but not the STL stack container).
Requirements:
must be able to store elements of an arbitrary type
every instance accepts insertions as long as the system has enough free memory
must be in namespace cop4530
must use most of the methods and operator overloads shown in header file below
(not back(), +=op, []ops)
methods/functions, etc declared in .h, and implemented in separate .hpp
I then use the stack with another program I create that changes infix notation arithmetic to postfix, and evaluates it if all the elements are comparable.
My professor gave an example header file of what this may look like, which is shown below.
Why does he use a deque pointer??
I've searched and found many cases where people adapt a STL container to a stack, but never an explanation for a STL container as a pointing to a stack. Could someone explain the benefits of this over using a non pointer, if there are any? Examples help
Example .h declaration file
#ifndef COP4530_STACK_H
#define COP4530_STACK_H
#include <iostream>
#include <deque>
namespace cop4530
{
template <typename T>
class Stack;
//----------------------------------
// Stack<T>
//----------------------------------
template <typename T>
class Stack
{
public:
// Constructor, Copy-constructor and destructor
Stack ();
Stack (const Stack<T>&);
Stack (Stack<T> &&);
~Stack ();
// member operators
Stack<T>& operator = (const Stack<T>&);
Stack<T> & operator=(Stack<T> &&);
Stack<T>& operator += (const Stack<T>&);
const T& operator [] (int) const;
T& operator [] (int);
// other methods
int size () const;
int capacity () const;
// Container class protocol
bool empty () const;
void clear ();
void push (const T&);
void push (T &&);
void pop ();
T& top ();
const T& top () const;
T& back ();
// Display methods
void print (std::ostream& os, char ofc = ' ') const;
protected:
std::deque<T> *mystack; // pointer to the stack.
//std::deque<T> mystack; //WHY NOT THIS???
} ;
// operator overloads
template < class T >
std::ostream& operator << (std::ostream& os, const Stack<T>& a);
template < class T >
bool operator == (const Stack<T>&, const Stack<T>&);
template < class T >
bool operator != (const Stack<T>&, const Stack<T>&);
template < class T >
bool operator <= (const Stack<T>&, const Stack<T>&);
#include "stack.hpp"
} // namespace cop4530
#endif
Example .hpp implementation
#ifndef COP4530_STACK_HPP
#define COP4530_STACK_HPP
//----------------------------------------
// Stack<T>:: Implementations
//----------------------------------------
// operator overloads
template <typename T>
std::ostream& operator << (std::ostream& os, const Stack<T>& s)
{
}
template <typename T>
bool operator<=(const Stack<T>& s1, const Stack<T>& s2)
{
}
template <typename T>
bool operator == (const Stack<T>& s1, const Stack<T>& s2)
{
}
template <typename T>
bool operator != (const Stack<T>& s1, const Stack<T>& s2)
{
}
// public methods
template <typename T>
Stack<T>::Stack()
//Constructor
{
}
template <typename T>
Stack<T>::Stack(const Stack<T>& source)
//Copy-constructor
{
}
template <typename T>
Stack<T>::Stack(Stack<T> && source)
{
}
template <typename T>
Stack<T>::~Stack()
// destructor
{
}
template <typename T>
Stack<T>& Stack<T>::operator = (const Stack<T>& source)
// assignment operator
{
}
template <typename T>
Stack<T>& Stack<T>::operator = (Stack<T> && source)
{
}
template <typename T>
Stack<T>& Stack<T>::operator += (const Stack<T>& source)
{
}
template <typename T>
const T& Stack<T>::operator [] (int i) const
// element operator
{
}
template <typename T>
T& Stack<T>::operator [] (int i)
// element operator
{
}
template <typename T>
bool Stack<T>::empty() const
{
}
template <typename T>
int Stack<T>::size() const
{
}
template <typename T>
void Stack<T>::push(const T& Val)
{
}
template <typename T>
void Stack<T>::push(T && Val)
{
}
template <typename T>
void Stack<T>::pop()
{
}
template <typename T>
void Stack<T>::clear()
{
}
template <typename T>
T& Stack<T>::top()
{
}
template <typename T>
const T& Stack<T>::top() const
{
}
template <typename T>
T& Stack<T>::back()
{
}
template <typename T>
void Stack<T>::print(std::ostream& os, char ofc) const
{
}
#endif

C++ friends in template classes, separation of interface and implementation [duplicate]

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 7 years ago.
The following code works fine:
Class.h:
#ifndef ClassLoaded
#define ClassLoaded
#include <iostream>
template <class T> class Class{
public:
template <class T> friend std::ostream& operator<<(std::ostream& Stream, const Class<T>& Op);
};
#endif
Class.cpp:
#include "Class.h"
template class Class<int>;
template std::ostream& operator<<(std::ostream& Stream, const Class<int>& Op);
template <class T> std::ostream& operator<<(std::ostream& Stream, const Class<T>& Op){
return(Stream);
}
Main.cpp:
#include "Class.h"
#include <iostream>
using namespace std;
int main(){
Class<int> Test;
cout << Test << endl;
return(0);
}
but the following extended version gives a linker error (unresolved external symbol) and I do more or less understand why. But how to fix it?
Class.h:
#ifndef ClassLoaded
#define ClassLoaded
#include <iostream>
template <class T> class Class{
public:
class SubClass{
public:
friend std::ostream& operator<<(std::ostream& Stream, const SubClass& Op);
};
template <class T> friend std::ostream& operator<<(std::ostream& Stream, const Class<T>& Op);
private:
SubClass Member;
};
#endif
Class.cpp:
#include "Class.h"
template class Class<int>;
template std::ostream& operator<<(std::ostream& Stream, const Class<int>& Op);
template <class T> std::ostream& operator<<(std::ostream& Stream, const typename Class<T>::SubClass& Op){
return(Stream);
}
template <class T> std::ostream& operator<<(std::ostream& Stream, const Class<T>& Op){
Stream << Op.Member;
return(Stream);
}
Main.cpp:
#include "Class.h"
#include <iostream>
using namespace std;
int main(){
Class<int> Test;
cout << Test << endl;
return(0);
}
I guess I need an analogue of the lines
template class Class<int>;
template std::ostream& operator<<(std::ostream& Stream, const Class<int>& Op);
for SubClass and also some sort of template version of
friend std::ostream& operator<<(std::ostream& Stream, const SubClass& Op);
but how to do it?
Edit: As this was claimed to be a duplicated of another question: My question here is very specific (see comments below) and is not answered by the quoted questions or even mentioned there.
Just provide the definitions of the template functions in the .hpp files.
I believe the following should work:
template <class T> class Class {
SubClass member;
public:
class SubClass {
public:
friend std::ostream& operator<<(std::ostream& Stream, const Class<T>& Op) {
return Stream;
}
};
}

Why would this template not compile?

I have a pretty simple template which is a container which is an array of T. I am getting a syntax error :
container.h(7): error C2143: syntax error : missing ';' before '&'. I have tried removing the declaration there but then the error just skips over to the definition. Would appreciate any help.
EDIT: now i fixed the using namespace thing, but another error popped:
container.h(8): error C2975: 'Container' : invalid template argument for 'unnamed-parameter', expected compile-time constant expression
#include <typeinfo.h>
#include <assert.h>
#include <iostream>
#pragma once
using namespace std;
template <typename T, int> class Container;
template <typename T, int> ostream& operator<< <>(ostream &, const Container<T,int> &);
template<class T , int capacity=0> class Container
{
//using namespace std;
private:
T inside[capacity];
public:
Container()
{
}
~Container(void)
{
}
void set(const T &tType, int index)
{
assert(index>=0 && index<= capacity);
inside[index] = tType;
}
T& operator[](int index)
{
assert(index>=0 && index<= capacity);
return inside[index];
}
friend ostream& operator<< <>(ostream& out, const Container<T,int> c);
{
for(int i=0;i<sizeof(inside)/sizeof(T);i++)
out<<c.inside[i]<< "\t";
return out;
}
};
You probably want:
template <typename T, int N>
ostream& operator<<(ostream &, const Container<T,N> &);
// ^ here you need N, not int!
or, since you don't actually need the forward declaration, you can simply use this implementation in your class:
friend ostream& operator<<(ostream & out, const Container<T,capacity>& c)
{
for(int i=0;i<capacity;++i)
out<<c.inside[i]<< "\t";
return out;
}
You want something like:
template <typename T, int N>
friend ostream& operator<<(ostream & out, const Container<T,N>& c) {
for(int i=0;i<sizeof(inside)/sizeof(T);i++)
out<<c.inside[i]<< "\t";
return out;
}

Undefined reference to friend function in template class

The following codes are in file Heap.h
template <typename T>
class Heap {
public:
Heap();
Heap(vector<T> &vec);
void insert(const T &value);
T extract();
T min();
void update(int index, const T &value);
/* for debug */
friend ostream &operator<< (ostream &os, const Heap<T> &heap);
#if 0
{
for (int i = 0; i < heap.vec_.size(); i++) {
os << heap.vec_[i] << " ";
}
return os;
}
#endif
private:
void minHeapify(int index);
int left(int index);
int right(int index);
int parent(int index);
void swap(int, int);
vector<T> vec_;
};
template <typename T>
ostream &operator<<(ostream &os, const Heap<T> &heap)
{
for (int i = 0; i < heap.vec_.size(); i++) {
os << heap.vec_[i];
}
return os;
}
In a testheap.cpp file, I use this template class, when I compile, an undefined reference to the << operator overloading function error occur. Confused with this situation.
When I put the definition of the function in the class, it works.
The OS is Ubuntu, compiler is g++.
The following should work:
template <typename T>
class Heap {
public:
...
template<class U>
friend ostream &operator<<(ostream &os, const Heap<U> &heap);
...
};
template <typename T>
ostream &operator<<(ostream &os, const Heap<T> &heap)
{
...
}
Try this :
template <typename T2>
friend ostream &operator<< (ostream &os, const Heap<T2> &heap);
I had the same problem. Here is the question