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.
Related
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>&);
};
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.
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;
}
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
I've been having issues with using templates for a vector class. For some reason marime (size) is getting received as a pointer. I've managed to relieve the code of errors. Some help would be welcomed.
#include <iostream>
#include <stdio.h>
using namespace std;
template <class T>
class Vector {
private: int marime; T *vect;
public: Vector (int marime = 0){vect = new T[marime];}
~Vector (){
if ( vect != NULL ) delete [] vect;
}
int getMarime();
T getVect(int);
void setMarime(int);
void setVect(T,int);
Vector <T> operator+ (Vector);
Vector <T> operator= (Vector);
template <class U> friend istream & operator >>(istream, Vector);
template <class U> friend ostream & operator <<(ostream, Vector);
};
template <class T >
istream & operator>> (istream & in, Vector<T> & v)
{
T val;
int marime = v.getMarime();
for (int i=0;i<marime; i++) {
in>>val;
v.setVect(val,i);
}
return in;
}
template <class T>
ostream & operator<< (ostream& out, Vector<T> & v)
{
for (int i=0;i<v.getMarime(); i++)
out<<v.getVect(i)<< " " ;
return out;
}
template <class T>
int Vector<T>::getMarime(){
return marime;
}
template <class T>
T Vector<T>::getVect(int i){
return vect[i];
}
template <class T>
void Vector<T>::setMarime(int n){
this->marime = n;
}
template <class T>
void Vector<T>::setVect(T val, int i){
this->vect[i] = val;
}
template <class T>
Vector<T> Vector<T>::operator +(Vector<T> vector){
Vector<T> temp(marime + vector.marime);
for (int i=0; i < marime; i++)
temp.vect[i] = vect[i];
for (int i=marime+1; i<temp.marime; i++)
temp.vect[i] = vector.vect[i];
return *temp;
}
template <class T>
Vector<T> Vector<T>::operator= (Vector<T> vector){
Vector<T> temp(vector.marime);
for (int i=0; i < vector.marime; i++) temp.vect[i] = vector.vect[i];
return *temp;
}
int main() {
int n=3;
Vector <int> A(n);
cin>>A;
cout<<A;
return 0;
}
You are failing to initialize marime. You need to do this:
public: Vector (int marime = 0) : marime(marime) {vect = new T[marime];}
otherwise it just contains an essentially random value.
To avoid confusion it is probably better not to use the name of the member variable as a constructor parameter name. It is quite common to use naming conventions for member variables, such as starting with m_, or finishing with an underscore (marime_).
public: Vector (int marime = 0){vect = new T[marime];}
Shouldn't there be a this->marine = marime?