Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overload operator<< for template class

I am having problem with overloading operator<< for a template class. I am using Visual Studio 2010, and here is my code.

#ifndef _FINITEFIELD
#define _FINITEFIELD
#include<iostream>

namespace Polyff{
    template <class T, T& n> class FiniteField;
    template <class T, T& n> std::ostream& operator<< (std::ostream&, const FiniteField<T,n>&);

    template <class T, T& n> class FiniteField {
    public:
            //some other functions
    private:
        friend std::ostream& operator<< <T,n>(std::ostream& out, const FiniteField<T,n>& obj);
        T _val;
    };

    template <class T, T& n>
    std::ostream& operator<< (std::ostream& out, const FiniteField<T,n>& f) {
        return  out<<f._val;
    }
    //some other definitions
}
#endif

In main I just have

#include"FiniteField.h"
#include"Integer.h"
#include<iostream>
using std::cout;
using namespace Polyff;
Integer N(5);

int main () {

    FiniteField<Integer, N> f1;
    cout<< f1;  
}

where Integer is just a wrapper of int with some special functionality I need.

However, when I compile the above code, I got error C2679, which says binary '<<' : no operator found which takes a right-hand operand of type 'Polyff::FiniteField<T,n>' (or there is no acceptable conversion)

I have also tried to remove the parameters in the friend declaration so the code becomes:

friend std::ostream& operator<< <> (std::ostream& out, const FiniteField<T,n>& obj);

But this produce another error: C2785: 'std::ostream &Polyff::operator <<(std::ostream &,const Polyff::FiniteField<T,n> &)' and '<Unknown>' have different return types

so I am wondering how should I change the code so it compiles and why? Thanks!

------------------------- edited on 2012.12.31 ---------------------------

The code compiles with g++ now. Here is the github repository.

like image 241
tgeng Avatar asked Dec 31 '12 08:12

tgeng


1 Answers

This seem to work as expected:

namespace Polyff{
  template <class T, T* n> class FiniteField;
  template <class T, T* n> std::ostream& operator<< (std::ostream&, const FiniteField<T,n>&);

  template <class T, T* n> class FiniteField {
  public:
    //some other functions
  private:
    friend std::ostream& operator<< <T,n>(std::ostream& out, const FiniteField<T,n>& obj);
    T _val;
  };

  template <class T, T* n>
  std::ostream& operator<< (std::ostream& out, const FiniteField<T,n>& f) {
    return  out << f._val.n; // I added the field of my Integer class
  }
  //some other definitions
}


struct Integer{
  Integer() : n(0){}
  Integer(int nn) : n(nn){}
  int n;
};

using std::cout;
using namespace Polyff;
Integer N(5);

int main () {
  FiniteField<Integer, &N> f1;
  cout<< f1;  
}

I just replaced the reference by the pointer of your object in the template arguments, since a pointer to a global object (static or not) is an information known at compile-time (or at least link time). I am not aware of the language accepting references.

Note that in this example, 0 will be printed because it corresponds to the default construction of _val.

like image 190
Raffi Avatar answered Sep 23 '22 16:09

Raffi