1

My class looks like:

class FileOut
{
private:
    std::ofstream stream;
public:
    FileOut(string sciezka);
    ~FileOut(void);

    friend FileOut & operator<< (FileOut & obiekt, const char* w);
    friend FileOut & operator<< (FileOut & obiekt, const string & w);
    friend FileOut & operator<< (FileOut & obiekt, const char & znak);
    friend FileOut & operator<< (FileOut & obiekt, const int & liczba);
    friend FileOut & operator<< (FileOut & obiekt, const double & liczba);
    friend FileOut & operator<< (FileOut & obiekt, std::endl);
    //friend FileOut & endl (FileOut & obiekt);
};

operator<< works fine for strings, char, int etc. (I put new characters to stream). I want to implement manipulator endl for my class. Generally we override it this way:

ostream & endl (ostream & os){ return os << '\n'; }

but it won't work for my class. I declared

friend FileOut & endl (FileOut & obiekt);

but it doesn't work. How can I do it to be able to write:

FileOut save("file.txt");
save<<"tralalala"<<endl<<1123;

???

j883376
  • 1,125
  • 9
  • 18
Danu
  • 77
  • 2
  • 10
  • 1
    Is [this question/answer](http://stackoverflow.com/questions/2212776/overload-handling-of-stdendl?rq=1) similar to what you're trying to do? Or perhaps [this one](http://stackoverflow.com/questions/15215010/using-ofstream-wrapper-class-with-overloaded-operator-on-endl?rq=1) ? – WhozCraig May 29 '13 at 18:04
  • 1
    What 'doesnt work'? Are you getting compiler errors, unexpected output, random implosions of your television? – Marc Claesen May 29 '13 at 18:16
  • 1) error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'FileOut &(__cdecl *)(FileOut &)' (or there is no acceptable conversion). 2) IntelliSense: no operator "<<" matches these operands FileOut &obiekt) – Danu May 29 '13 at 18:38

2 Answers2

2

Since std::eol is actually a function template of the type compatible with ostream& (*fctr) (ostream&), you need to overload the following operator:

class FileOut
{
//...    
friend FileOut & operator<< (FileOut & obiekt, ostream& (*fctr) (ostream&))
//...
};

Inside the overload, you need to make sure that fctr actually matches eol (it can be eof, tab, or any manipulator matching the signature) and then write whatever it is you want to write to a file on eol:

#include <fstream>
#include <string>
#include <iostream>

using namespace std;

class FileOut
{
private:
    std::ofstream stream;
public:
    FileOut(std::string sciezka):stream(sciezka) {};
    ~FileOut(void){};

    friend FileOut & operator<< (FileOut & obiekt, const char* w) {obiekt.stream<<w;return obiekt;} ;
    friend FileOut & operator<< (FileOut & obiekt, const string & w);
    friend FileOut & operator<< (FileOut & obiekt, const char & znak);
    friend FileOut & operator<< (FileOut & obiekt, const int & liczba){obiekt.stream<<liczba;return obiekt;};
    friend FileOut & operator<< (FileOut & obiekt, const double & liczba);
    friend FileOut & operator<< (FileOut & obiekt, ostream& (*pf) (ostream&));
    //friend FileOut & endl (FileOut & obiekt);
};

FileOut & operator<< (FileOut & obiekt, ostream& (*pf) (ostream&))
{
    if(pf==&std::endl)
    {
        obiekt.stream<<"MY FAT JUICY EOL";
    }

    return obiekt;
}

int main(int argc, char* argv[])
{
    FileOut save("file.txt");

    save<<"tralalala"<<endl<<1123;
    return 0;
}
AlexK
  • 1,279
  • 8
  • 19
1

Alternatively, if you don't like using std::eol and want your own:

#include <fstream>
#include <string>
#include <iostream>

using namespace std;

class FileOut
{
private:
    std::ofstream stream;
public:
    FileOut(std::string sciezka):stream(sciezka) {};
    ~FileOut(void){};

    friend FileOut & operator<< (FileOut & obiekt, const char* w) {obiekt.stream<<w;return obiekt;} ;
    friend FileOut & operator<< (FileOut & obiekt, const string & w);
    friend FileOut & operator<< (FileOut & obiekt, const char & znak);
    friend FileOut & operator<< (FileOut & obiekt, const int & liczba){obiekt.stream<<liczba;return obiekt;};
    friend FileOut & operator<< (FileOut & obiekt, const double & liczba);
    friend FileOut & operator<< (FileOut & obiekt, void (*pf) ());

    static void eol() {};
    //friend FileOut & endl (FileOut & obiekt);
};

FileOut & operator<< (FileOut & obiekt, void (*pf) ())
{
    if(pf == FileOut::eol)
    {
        obiekt.stream<<"MY FAT JUICY STATIC EOL";
    }

    return obiekt;
}

int main(int argc, char* argv[])
{
    FileOut save("file.txt");

    save<<"tralalala"<<FileOut::eol<<1123;
    return 0;
}
AlexK
  • 1,279
  • 8
  • 19
  • It's generally complicated for me, but the code you showed is short and OK. Both versions works. Alternative form is better I think, but I don't want to use it form only because I would have to write `FileOut::endl` instead of just `endl` - it's inconvenient. But when I compile first version (in Visual Studio 2012) I get "error": IntelliSense: cannot determine which instance of overloaded function "std::endl" is intended. But program compiles and work correctly, I think :) Thank you very much! – Danu May 30 '13 at 16:58
  • @Danu: Yeah, looks like IntelliSense is still catching up to C++ 11 as I get the same thing. I am glad that you like the answers, please upvote and/or accept the one that works best for you, or both :) Thanks ! – AlexK May 30 '13 at 17:38