Friend function unable to determine type in parameter

Viewed 43

In my vector.h header file I have:

template <typename T>
class Vector{
private:
    int sz:
    T* buf;
public:
//member functions all the way down
friend ostream& operator << (ostream & o, const Vector & v);
};

In my vector.cpp file I have this:

#include "vector.h"
using namespace std;
//member functions defined

std::ostream& operator << (std::ostream & o, const Vector & v){
 return o;
}

I am getting a compiler error stating that "Vector" is an unknown type name in the line where operator << is defined. Could anyone help me figure out why this is? I am not allowed to change the header file.

2 Answers

Implementing the operator<< function as

std::ostream& operator << (std::ostream & o, const Vector & v){
   return o;
}

does not work since Vector is a template, not a type. You'll have to use:

template <typename T>
std::ostream& operator << (std::ostream & o, const Vector<T> & v){
   return o;
}

However, that will reveal more problems. Note that the above implementation makes the above operator<< a function a template, not a function. The friend declaration inside the class does not use a function template. It uses a function. That's not correct.

To do this right, you'll have to:

  1. Declare the class template.
  2. Declare the function template.
  3. Declare a specific instantiation of the function template a friend of the class template.

Here's a minimal program that works for me.

#include <iostream>

// Delcare the class template
template <typename T> class Vector;

// Declare the function template
template <typename T>
std::ostream& operator << (std::ostream & o, const Vector<T> & v);

template <typename T>
class Vector{
   private:
      int sz;
      T* buf;
   public:
      Vector(int s) : sz(s) {}

      // Friend declaration that uses a specific instantiation of the function template.
      // Note that operator<< <int> is a function of Vector<int> only, not that
      // of Vector<double> or any other instantiaton of Vector.
      friend std::ostream& operator<< <T> (std::ostream & o, const Vector & v);
};

// Implement the function template.
template <typename T>
std::ostream& operator << (std::ostream & o, const Vector<T> & v){
   return (o << v.sz);
}

int main()
{
   Vector<int> v(10);
   std::cout << v << std::endl;
}

You said,

I am not allowed to change the header file.

That's unfortunate. Perhaps you can persuade your teacher to change their mind or update the .h file to allow a clean solution to be implemented.

Your vector is a template class. Hence the compiler knows no Vector. He only knows Vector<...someType...>.

So you can write something like this

std::ostream& operator << (std::ostream & o, const Vector<int> & v){
 return o;
}

With this function, a minimal working example which doesn't modify the header would be:

template <typename T>
class Vector
{
private:
    int sz;
    T* buf;

public:
    // member functions all the way down
    friend std::ostream& operator<<(std::ostream& o, const Vector& v);
};


std::ostream& operator<<(std::ostream& o, const Vector<int>& v)
{
    return o;
}

int main()
{
    Vector<int> a;
    std::cout << a << std::endl;
}

However, to get a general offstream operator, you have to use another template:

template <typename T>
std::ostream& operator<<(std::ostream& o, const Vector<T>& v)
{
    return o;
}

In this case, the implementation should stay in the header. Otherwise, you can use it only in your Vector.cpp because templates do not produce any code until they are instantiated. As a result, every file that wants to use the operator needs to know the implementation of the template to generate the necessary code.

Also, in order to work correctly, you have to adjust the friend declaration:

template <typename T2>
friend std::ostream& operator<<(std::ostream& o, const Vector<T2>& v);

For a smarter way to adjust the friend declaration have a look at the answer of R Sahu

Related