Undefined reference C++ with template class [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Undefined reference error for template method
Splitting templated C++ classes into .hpp/.cpp files--is it possible?
I have this class:
matrix.h
#ifndef MATRIX_H
#define MATRIX_H
#include <vector>
#include <iostream>
using namespace std;
template <class T> class matrix;
template <typename T> ostream& operator<< (ostream& o, const matrix<T>& m);
template <class T>
class matrix
{
public:
matrix(const int&);
void push(const T&);
void setRows(const int&);
int size();
T& operator ()(const int&, const int&);
friend ostream& operator<< <>(ostream&, const matrix<T>&);
virtual ~matrix();
private:
vector<T> elements_;
int dimension_;
};
#endif // MATRIX_H
#include "matrix.h"
#include <vector>
matrix.cpp
template <class T>
matrix<T>::matrix(const int& n)
{
dimension_ = n;
}
template <class T>
void matrix<T>::push(const T& element)
{
elements_.resize( elements_.size() + 1, element);
}
template <class T>
int matrix<T>::size()
{
return elements_.size()/dimension_;
}
template <class T>
T& matrix<T>::operator ()(const int &n, const int &m)
{
if ((n < 0) || (n > dimension_))
{
cerr << "Row index out of range"
<< endl << endl;
}
if ((m < 0) || (m > dimension_))
{
cerr << "Column index out of range"
<< endl << endl;
}
return elements_[n*dimension_+m];
}
template <class T>
ostream& operator << (ostream& o, const matrix<T>& m)
{
for (int i = 0; i < m.size(); i++)
{
for (int j = 0; j < m.size(); i++)
{
o << m(i,j) << " ";
}
o << endl;
}
return o;
}
template <class T>
matrix<T>::~matrix()
{
//dtor
}
And this program:
#include "matrix.h"
#include <iostream>
using namespace std;
int main()
{
matrix<int> m(3);
m.push(10);
m.push(10);
m.push(11);
m.push(11);
m.push(12);
m.push(12);
m.push(13);
m.push(13);
m.push(10);
cout << m;
cout << "Hello world!" << endl;
return 0;
}
And for EACH. SINGLE. ONE. Of the methods I call, I get a compiler error like this one:
C:\Users...\main.cpp|8|undefined reference to
`matrix::matrix(int const&)'|
I have the matrix.cpp file built. I'm using Code::Blocks, so I have a matrix.o file in the obj folder. That's not the problem.
What is it?

Related

C++ unexpected syntax errors

Ok I have updated the code:
#ifndef VECTOR_H
#define VECTOR_H
#include<cstdlib>
#include<vector>
#include<iostream>
using namespace std;
template < typename T>
class MyClass
{
public:
MyClass() : size(10), index(0) { vec = new T[10]; };
MyClass(int i) : size(i), index(0) { vec = new T[i]; };
friend bool Add(T i);
virtual ~MyClass();
friend ostream& operator<<(ostream& out, const T& obj);
private:
T * vec;
int size;
int index;
};
template <typename T>
virtual MyClass<T>::~MyClass()
{
delete[] vec;
}
template <typename T>
ostream& operator<<(ostream& out, const MyClass<T>& obj){
for (int i = 0; i < index; ++i)
out << obj[i] << " ";
out << endl;
}
template <typename T>
bool MyClass<T>::Add(T i){
if (size == index){
size *= 2;
realloc(vec, size);
}
vec[index++] = i;
}
#endif // !VECTOR_H
Error list:
Error 1 error C2039: 'add' : is not a member of 'MyClass' c:\users\mihaibogdan\documents\visual studio 2013\projects\dashit\dashit\header.h 41
You should use qualified names
friend std::ostream& operator<<( std::ostream& out, const T& obj);
Standard C++ names are declared in name space std.
Otherwise the compiler looks up unqualified name ostream in the global name space where it is not of course declared.

Operator= doesn't work with std::vector c++ [duplicate]

This question already has answers here:
std::vector::resize() vs. std::vector::reserve()
(5 answers)
Closed 7 years ago.
I have a class
template <class T>
class General_matrix : public Math_object<T>
{
public:
General_matrix(const size_t m, const size_t n);
~General_matrix();
void init();
void show();
T* operator()(const size_t, const size_t) const;
General_matrix<T> operator*(const General_matrix<T>&);
};
derived from
template <class T>
class Math_object
{
protected:
size_t size_m, size_n;
std::vector <T> field;
public:
Math_object(const size_t m, const size_t n);
virtual ~Math_object() = 0;
virtual void show() = 0;
virtual void init() = 0;
};
Operator * doesn't work properly. The building of auxiliary matrix within an operator is OK, but when it comes to returning it changes only the integer data fields in receiving matrix. It turned out that the problem is with operator= for std::vector. I don't want to override it. Has anyone else faced this problem? Why can't I assign vector to vector of the same size?
template <typename T>
General_matrix<T> General_matrix<T>::operator*(const General_matrix<T> &right_operand)
{
General_matrix<T> aux(this->size_m, right_operand.size_n);
T collector;
for (int i=0; i<this->size_m; i++)
{
for (int j=0; j<right_operand.size_n; j++)
{
collector = 0;
for (int k=0; k<this->size_n; k++)
{
collector += *((*this)(i,k)) * *(right_operand(k,j));
}
*(aux(i,j)) = collector;
}
}
return aux;
}
UPD: Here is a MCVE
There are 2 matrices with values {{0,1,2},{3,4,5}} and {{0,1},{2,3},{4,5}}. The result of their multiplication must be {{10,13},{28,40}} and it is {{0,0},{0,0}}.
#include <iostream>
#include <vector>
using namespace std;
template <class T>
class Math_object
{
protected:
size_t size_m, size_n;
std::vector <T> field;
public:
Math_object(const size_t m, const size_t n);
virtual ~Math_object() = 0;
virtual void show() = 0;
virtual void init() = 0;
};
template <class T>
class General_matrix : public Math_object<T>
{
public:
General_matrix(const size_t m, const size_t n);
~General_matrix();
void init();
void show();
T* operator()(const size_t, const size_t) const;
General_matrix<T> operator*(const General_matrix<T>&);
};
template <typename T>
Math_object<T>::Math_object(const size_t m, const size_t n/*=1*/)
{
cout << "Constructor MO"<<"\n";
size_m=m;
size_n=n;
field.reserve(m*n);
}
template <typename T>
Math_object<T>::~Math_object()
{
cout << "Destructor MO"<<"\n";
vector<T>().swap(this->field);
}
template <typename T>
void Math_object<T>::show() {};
template <typename T>
General_matrix<T>::General_matrix(const size_t m, const size_t n):Math_object<T>(m,n)
{
cout << "Constructor GM"<<"\n";
}
template <typename T>
General_matrix<T>::~General_matrix()
{
cout << "Destructor GM"<<"\n";
}
template <typename T>
void General_matrix<T>::init()
{
cout << "Input matrix"<<"\n";
for (int i=0; i<this->size_m*this->size_n; i++)
this->field[i] = i;
}
template <typename T>
T* General_matrix<T>::operator()(const size_t i, const size_t j) const
{
return const_cast<T*>(&(this->field[i*(this->size_n)+j]));
}
template <typename T>
void General_matrix<T>::show()
{
for (int i=0; i < this->size_m; i++)
{
for (int j=0; j < this->size_n; j++)
{
cout << *((*this)(i,j)) << " ";
}
cout << "\n";
}
}
template <typename T>
General_matrix<T> General_matrix<T>::operator*(const General_matrix<T> &right_operand)
{
General_matrix<T> aux(this->size_m, right_operand.size_n);
T collector;
for (int i=0; i<this->size_m; i++)
{
for (int j=0; j<right_operand.size_n; j++)
{
collector = 0;
for (int k=0; k<this->size_n; k++)
{
collector += *((*this)(i,k)) * *(right_operand(k,j));
}
*(aux(i,j)) = collector;
}
}
return aux;
}
template class Math_object<int>;
template class Math_object<float>;
template class General_matrix<int>;
template class General_matrix<float>;
int main()
{
General_matrix<int> k(2,3);
k.init();
General_matrix<int> p(3,2);
p.init();
General_matrix<int> t(2,2);
t=k*p;
t.show();
return 0;
}
One problem, as mentioned in the comments, is the use of reserve instead of resize in the constructor.
But you have also undefined behavior in operator(). Better implement a const and a non-const version.

How do I declare a template friend function that is type-specific in my template class?

I've recently learned that there are two ways to declare a template friend class or function. For example, to declare a template friend class, you may do this
template <typename T>
class goo
{
template <typename T>
friend class foo;
};
or this
template <typename T>
class goo
{
friend class foo <T>;
};
These two declarations are in fact different. The former allows you to use any type of template friend class foo with any type of template friend class goo. Where as the latter only allows you to use the same type such that you may do foo<int> with goo<int> but not foo<int> with goo<char>.
In the header file below, I try to use the latter form of the declaration to make my template friend function friend std::ostream& operator<<(std::ostream&, const Array<T>&); more type-specific in an effort to make my program more encapsulated.
//ARRAY_H
#include <iostream>
#include "Animal.h"
const int DefaultSize = 3;
template <typename T> // declare the template and the paramenter
class Array // the class being parameterized
{
public:
Array(int itsSize = DefaultSize);
Array(const Array &rhs);
~Array() { delete[] pType; }
// operators
Array& operator=(const Array&);
T& operator[](int offSet) { return pType[offSet]; }
const T& operator[](int offSet) const { return pType[offSet]; }
// accessors
int GetSize() const { return itsSize; }
// friend function
friend std::ostream& operator<< <T>(std::ostream&, const Array<T>&);
private:
T *pType;
int itsSize;
};
template <typename T>
Array<T>::Array(int size = DefaultSize) :itsSize(size)
{
pType = new T[size];
for (int i = 0; i < size; i++)
pType[i] = static_cast<T>(0);
}
Array<Animal>::Array(int AnimalArraySize) :itsSize(AnimalArraySize)
{
pType = new Animal[AnimalArraySize];
}
template <typename T>
Array<T>::Array(const Array &rhs)
{
itsSize = rhs.GetSzie();
pType = new T[itsSize];
for (int i = 0; i < itsSize; i++)
pType[i] = rhs[i];
}
template <typename T>
Array<T>& Array<T>::operator=(const Array &rhs)
{
if (this == &rhs)
return *this;
delete[] pType;
itsSize = rhs.GetSize();
pType = new T[itsSize];
for (int i = 0; i < itsSize; i++)
pType[i] = rhs[i];
return *this;
}
template <typename T>
std::ostream& operator<<(std::ostream& output, const Array<T> &theArray)
{
for (int i = 0; i < theArray.GetSize(); i++)
output << "[" << i << "]" << theArray[i] << std::endl;
return output;
}
#endif
However, I receive a compiler error "error C2143: syntax error : missing ';' before '<'" for line 23 which is friend std::ostream& operator<< <T>(std::ostream&, const Array<T>&);.
When using the former form of the declaration by changing line 23 to this
template <typename T>
friend std::ostream& operator<<(std::ostream&, const Array<T>&);
My program executes without any errors.
I assume I cannot use the same syntax from type-specific template friend classes for type-specific template friend functions, or that I may be missing some kind of forward declaration. I've searched through stack-overflow and the closest topic I could find for this problem is here, but they only discuss type-specific template friend classes. I am unable to find a topic that discusses the correct syntax for using a template friend function in this way.
If this is a syntax error, what is the correct way to declare my type-specific template friend function? If this is not a syntax error, why will my program not compile?
Here are the rest of my project files for your reference. The desired behavior of my program is to show how a parametrized array uses a template to create multiple instances of different array types.
//ANIMAL_H
#ifndef ANIMAL_H
#define ANIMAL_H
#include <iostream>
class Animal
{
public:
// constructors
Animal();
Animal(int);
~Animal();
// accessors
int GetWeight() const { return itsWeight; }
void SetWeight(int theWeight) { itsWeight = theWeight; }
// friend operators
friend std::ostream& operator<<(std::ostream&, const Animal&);
private:
int itsWeight;
};
#endif
//ANIMAL.CPP
#include "Animal.h"
#include <iostream>
Animal::Animal() :itsWeight(0)
{
std::cout << "animal() ";
}
Animal::Animal(int weight) : itsWeight(weight)
{
std::cout << "animal(int) ";
}
Animal::~Animal()
{
std::cout << "Destroyed an animal...";
}
std::ostream& operator<<(std::ostream& theStream, const Animal& theAnimal)
{
theStream << theAnimal.GetWeight();
return theStream;
}
//MAIN.CPP
#include <iostream>
#include "Animal.h"
#include "Array.h"
void IntFillFunction(Array<int>& theArray);
void AnimalFillFunction(Array<Animal>& theArray);
int main()
{
Array<int> intArray;
Array<Animal> animalArray;
IntFillFunction(intArray);
AnimalFillFunction(animalArray);
std::cout << "intArray...\n" << intArray;
std::cout << "\nanimalArray...\n" << animalArray << std::endl;
std::cin.get();
return 0;
}
void IntFillFunction(Array<int>& theArray)
{
bool Stop = false;
int offset, value;
while (!Stop)
{
std::cout << "Enter an offset (0-9) and a value. ";
std::cout << "(-1 to stop): ";
std::cin >> offset >> value;
if (offset < 0)
break;
if (offset > 9)
{
std::cout << "***Please use values between 0 and 9.***\n";
continue;
}
theArray[offset] = value;
}
}
void AnimalFillFunction(Array<Animal>& theArray)
{
Animal *pAnimal;
for (int i = 0; i < theArray.GetSize(); i++)
{
pAnimal = new Animal(i * 10);
theArray[i] = *pAnimal;
delete pAnimal;
}
}
You need to declare the function template before you refer to a specialization as a friend.
// Forward declare class template.
template <typename T> class Array;
// Declare function template.
template <typename T>
std::ostream& operator<<(std::ostream& os, const Array<T>& arr);
template <typename T>
class Array
{
//...
friend std::ostream& operator<< <>(
std::ostream& os, const Array<T>& arr);
//...
};
You need a forward declaration of the function template (just as you need with a class template) in order to friend a specialization. Your code should be:
template <typename T>
std::ostream& operator<<(std::ostream& output, const Array<T> &theArray);
template <typename T>
class Animal
{
// ...
friend std::ostream& operator<< <T>(std::ostream&, const Array<T>&);
};

template classes as template parameters

How to define a function template-ed on a container and a type?
For example, overload insertion operator to stream all the elements of a vector, list, or, forward iterator container:
using namespace std;
#include <iostream>
#include <vector>
#include <list>
//...
//...the second argument is a container template-ed on type T
//...
template <typename T,template <typename U> class C>
ostream&
operator<<
(ostream& p_os,const C<T>& p_c)
{
for(typename C<typename T>::const_iterator cit=p_c.begin();cit!=p_c.end();++cit)
{
p_os.operator<<(*cit);
}
return p_os;
}
int
main
()
{
vector<int> v;
cout << v << endl;
list<int> l;
cout << l << endl;
return 0;
}
This does not compile on g++ 4.9. What is wrong? How is it done?
Why not just pass the container type as template parameter, and find out the element type from it? In your example code you don't even need the element type:
template <typename C>
ostream&
operator<<
(ostream& p_os,const C& p_c)
{
typedef typename C::value_type element_type; // if needed
for(typename C::const_iterator cit=p_c.begin();cit!=p_c.end();++cit)
{
p_os.operator<<(*cit);
}
return p_os;
}
(Although it might be unwise to use this for global functions like this without some enable_if trickery, since it will otherwise match any argument.)
EDIT: You could for example attempt to restrict this to classes with a nested value_type (which all containers have):
template <typename C, typename T = typename C::value_type>
ostream&
operator<<
(ostream& p_os,const C& p_c)
std::vector is a class template that has two template type parameters:
template <class T, class Alloc = allocator<T> >
class vector;
To make your function working with std::vector (and other two-parameter class templates) you can use the following definition:
template <typename T, typename A, template <typename, typename> class C>
// ~~~~~~~~~^ ~~~~~~~^
ostream& operator<<(ostream& p_os, const C<T,A>& p_c)
// ^^
{
for(typename C<T,A>::const_iterator cit=p_c.begin();cit!=p_c.end();++cit)
{
p_os.operator<<(*cit);
}
return p_os;
}
or alternatively:
template <typename T, template <typename...> class C>
ostream& operator<<(ostream& p_os, const C<T>& p_c);
Alan Stokes approach works. The code below can stream any container. I just had to add an insertion operator for maps
using namespace std;
#include <iostream>
#include <vector>
#include <list>
#include <forward_list>
#include <set>
#include <deque>
#include <array>
#include <map>
#include <unordered_map>
//...
//...needed for map types which are (key,value) pairs.
//...
template <typename K,typename V>
ostream&
operator<<
(ostream& p_os,const pair<const K,V>& p_v)
{
std::operator<<(p_os,'(');
p_os << p_v.first;
std::operator<<(p_os,',');
p_os << p_v.second;
std::operator<<(p_os,')');
return p_os;
}
template <typename C, typename T = typename C::iterator>
ostream&
operator<<
(ostream& p_os,const C& p_c)
{
for(typename C::const_iterator cit=p_c.begin();cit!=p_c.end();++cit)
{
typename C::value_type v = *cit;
p_os << v;
std::operator<<(p_os,",");
}
return p_os;
}
int
main
()
{
vector<int> v;
for(int i=0;i<4;++i)
{
v.push_back(i);
}
cout << v << endl;
list<int> l;
for(int i=0;i<4;++i)
{
l.push_back(i);
}
cout << l << endl;
forward_list<int> fl = {0,1,2,3};
cout << fl << endl;
set<int> s;
for(int i=0;i<4;++i)
{
s.insert(i);
}
cout << s << endl;
deque<int> d;
for(int i=0;i<4;++i)
{
d.push_back(i);
}
cout << d << endl;
array<int,4> a = {0,1,2,3};
cout << a << endl;
unordered_map<int,int> um;
for(int i=0;i<4;++i)
{
um[i] = i;
}
cout << um << endl;
map<int,int> m;
for(int i=0;i<4;++i)
{
m[i] = i;
}
cout << m << endl;
return 0;
}

Strange behavior of templated operator<<

I cant understand a behavior of operator<< in my class:
header:
#ifndef VECTOR_H_
#define VECTOR_H_
#include <string>
#include <iostream>
template<class T>
class Vector {
static const int EXPANDER = 10;
T* array;
int next;
int length;
void expand();
void contract();
public:
Vector();
Vector(const Vector& v);
void add(const T e);
T get(int index) const;
bool removeByIndex(int index);
bool remove(T e);
int size() const;
T operator[](int i) const;
T& operator+=(const T& t);
T operator+(const T& s);
friend std::ostream& operator<< (std::ostream& os, const Vector<T>& obj);
friend std::istream& operator>> (std::istream& is, Vector<T>& obj);
std::string toString();
~Vector();
};
#endif /* VECTOR_H_ */
vector.cpp
#include "Vector.h"
#include <string>
#include <sstream>
template<class T>
Vector<T>::Vector() {
length = EXPANDER;
next = 0;
array = new T[EXPANDER];
}
template<class T>
Vector<T>::Vector(const Vector& v) {
length = v.next + 1 + EXPANDER;
next = v.next;
array = new T[length];
for (int i = 0; i <= v.next; i++) {
array[i] = v.array[i];
}
}
template<class T>
void Vector<T>::add(const T e) {
if (next >= length - 1)
expand();
array[next++] = e;
}
template<class T>
T Vector<T>::get(int index) const {
if (index > next)
return -1;
return array[index - 1];
}
template<class T>
bool Vector<T>::removeByIndex(int index) {
if (index > next)
return false;
for (int i = index; i < length; i++) {
array[i] = array[i + 1];
}
next--;
contract();
return true;
}
template<class T>
bool Vector<T>::remove(T e) {
int index = -1;
for (int i = 0; i < next; i++) {
if (array[i] == e) {
index = i;
break;
}
}
if (index == -1)
return false;
return removeByIndex(index);
}
template<class T>
int Vector<T>::size() const {
return next;
}
template<class T>
void Vector<T>::expand() {
length += EXPANDER;
T* temp = new T[length];
for (int i = 0; i < next; i++) {
temp[i] = array[i];
}
delete[] array;
array = temp;
}
template<class T>
void Vector<T>::contract() {
if (next + EXPANDER >= length)
return; // NO need to contract
length = next + EXPANDER + 1;
T* temp = new T[length];
for (int i = 0; i < next; i++) {
temp[i] = array[i];
}
delete[] array;
array = temp;
}
template<class T>
T Vector<T>::operator[](int i) const {
return get(i);
}
template<class T>
T& Vector<T>::operator+=(const T& t) {
for (int i = 0; i < t.size(); i++) {
add(t.get(i));
}
return *this;
}
template<class T>
T Vector<T>::operator+(const T& s) {
this += s;
return this;
}
template<class T>
std::ostream& operator<< (std::ostream& os, Vector<T>& obj) {
os << obj.toString();
return os;
}
template<class T>
std::istream& operator>> (std::istream& is, Vector<T>& obj) {
int size;
T temp;
is >> size;
for (int i = 0; i < size; i++) {
is >> temp;
add(temp);
}
return is;
}
template<class T>
std::string Vector<T>::toString() {
using namespace std;
ostringstream sb;
sb << "Elements(" << size() << "): [";
for (int i = 0; i < next; i++) {
sb << array[i] << ", ";
}
string r;
r = sb.str();
r = r.substr(0, r.size() - 2) + string("]");
return r;
}
template<class T>
Vector<T>::~Vector() {}
and i run this code with main.cpp
#include "Vector.h"
#include "Vector.cpp"
#include <string>
#include <iostream>
using namespace std;
int main() {
Vector<int> v;
v.add(1);
v.add(2);
cout << v << endl;
}
the magic is in operator<< declaration in header. if i delete CONST modifier, compiler says: Undefined reference to operator<<, but with const it works. It is interesting that in my implementation, in cpp, I doesn't have CONST.
btw, how to solve warnings with warning: friend declaration declares a non-template function for operators?
You should learn how to boil this down to a Short, Self-Contained, Compilable Example aka Minimal Working Example.
Here's an SSCCE that demonstrates the problem:
#include <iostream>
template<class T>
class Vector
{
private:
T m;
public:
Vector(T p) : m(p) {}
friend std::ostream& operator<<(std::ostream& o, Vector<T> const& v);
T get() const { return m; }
};
template<class T>
std::ostream& operator<<(std::ostream& o, Vector<T>& v)
{
// accessing a private member leads to a compiler error here:
return o << "[function template]" << /*v.m*/ v.get();
}
// remove this function to get the same behaviour as in the OP
std::ostream& operator<<(std::ostream& o, Vector<int> const& v)
{
return o << "function" << v.m;
}
int main()
{
Vector<int> v(42);
std::cout << v;
}
Note that it's only about 30 lines long and fits onto one screen w/o scroll bars.
Now, the problem is based upon the friend declaration inside your class template:
friend std::ostream& operator<<(std::ostream& o, Vector<T> const& v);
This looks up a function named operator<< in the surrounding scopes, to befriend this already existing function. But it doesn't find any that matches those parameter type. Therefore, it declares a new function in the surrounding (= global) namespace. This function looks like this:
std::ostream& operator<<(std::ostream& o, Vector<T> const& v);
(in the global namespace)
Note: it can only be found via Argument-Dependent Lookup if it's only declared via a friend-declaration.
Now, you later declare a function template of the same name. But the compiler cannot know that you meant to befriend this function template when you wrote the friend declaration inside you class template before. So those two, the friend function and the function template, are unrelated.
What happens now is the usual overload resolution. The function template is preferred if you don't add a const, since you call it with a non-const argument:
Vector<int> v;
v.add(1);
v.add(2);
cout << v << endl; // v is not const
for this argument of type Vector<int>, the binding to Vector<int>& of the function template (specialization) is preferred over the binding to the Vector<int> const& of the friend function. Hence, the function template is chosen, which has a definition (function body) and everything compiles, links and works. Note that the function template is not befriended, but this doesn't raise an error since you don't use any private members.
Once you add the const to the function template, the function template is no longer a better match for the argument. As we have a function and a function template with the same overload "rank", the non-template is preferred. Ergo, the friend function is called, which has no definition => a linker error occurs.
The simplest solution is to define the friend function inside the class definition:
template<class T>
class Vector
{
private:
T m;
public:
Vector(T p) : m(p) {}
friend std::ostream& operator<<(std::ostream& o, Vector<T> const& v)
{
return o << v.m;
}
};
A solution using forward-declarations:
template<class T>
class Vector;
template<class T>
std::ostream& operator<<(std::ostream& o, Vector<T> const& v);
template<class T>
class Vector
{
private:
T m;
public:
Vector(T p) : m(p) {}
friend std::ostream& operator<< <T>(std::ostream& o, Vector<T> const& v);
};
template<class T>
std::ostream& operator<<(std::ostream& o, Vector<T> const& v)
{
return o << v.m;
}
Now, the compiler can find the forward-declared function template and befriend this existing function (the specialization of the function template) instead of declaring a new function.
A solution befriending the whole function template:
template<class T>
class Vector
{
private:
T m;
public:
Vector(T p) : m(p) {}
template<class U>
friend std::ostream& operator<<(std::ostream& o, Vector<U> const& v);
};
template<class T>
std::ostream& operator<<(std::ostream& o, Vector<T> const& v)
{
return o << v.m;
}
In this solution, the friend-declaration declares a function template, and the later declaration at namespace scope following the class' definition redeclares this function template.