2

I've not coded in C++ for a long time and I'm trying to fix some old code.

I'm geting the error:

TOutputFile& TOutputFile::operator<<(TOutputFile&, T)' must have exactly one argument

on the following code:

template<class T>
TOutputFile &operator<<(TOutputFile &OutFile, T& a);

class TOutputFile : public Tiofile{
public:
   TOutputFile (std::string AFileName);
   ~TOutputFile (void) {delete FFileID;}

   //close file
   void close (void) {
    if (isopened()) {
         FFileID->close();
         Tiofile::close();
      }
   }
   //open file
   void open  (void) {
      if (!isopened()) {
         FFileID->open(FFileName, std::ios::out);
         Tiofile::open();
      }
   }

   template<class T>
   TOutputFile &operator<<(TOutputFile &OutFile, const T a){
    *OutFile.FFileID<<a;
    return OutFile;
   }

protected:
   void writevalues  (Array<TSequence*> &Flds);
private:
   std::ofstream * FFileID;         


};

What's is wrong with that operator overloading ?

user3923073
  • 151
  • 2
  • 12
  • The function prototype should be after the class declaration/definition. – mch May 21 '19 at 11:38
  • 1
    Your definition of the `operator<<()` is inside the class, which means it is a member. As such, it has an implicit `this` parameter, in addition to the ones you have specified. Move the definition outside the class. (Then you're see other problems, but you haven't asked about those). – Peter May 21 '19 at 11:39
  • Making it a friend function will solve the issue, as it will no longer be a member function then. – CaptainDaVinci May 21 '19 at 11:40
  • Possible duplicate of [Can't Overload operator<< as member function](https://stackoverflow.com/questions/9814345/cant-overload-operator-as-member-function) – CaptainDaVinci May 21 '19 at 11:41

2 Answers2

5

Check the reference

The overloads of operator>> and operator<< that take a std::istream& or std::ostream& as the left hand argument are known as insertion and extraction operators. Since they take the user-defined type as the right argument (b in a@b), they must be implemented as non-members.

Hence, they must be non-member functions, and take exactly two arguments when they are meant to be stream operators.

If you are developing your own stream class, you can overload operator<< with a single argument as a member function. In this case, the implementation would look something like this:

template<class T>
TOutputFile &operator<<(const T& a) {
  // do what needs to be done
  return *this; // note that `*this` is the TOutputFile object as the lefthand side of <<
}
Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
0

Operator overloaded functions which are defined as member functions accept only one parameter. In case of overloading << operator, more than one parameter is required. Making it a friend function solves this issue.

class {
    ...
    friend TOutputFile &operator<<(TOutputFile &OutFile, const T &a);
    ...
};

template<class T>
TOutputFile &operator<<(TOutputFile &OutFile, const T &a) {
    *OutFile.FFileID << a;
    return OutFile;
}

A function marked as friend will allow that function to access private member of the class to which it is a friend.

CaptainDaVinci
  • 975
  • 7
  • 23