std::endl als Parameter in eigener Funktion



  • Guten Tag alle miteinander! 🙂
    Ich hab eine kleine Logbuchklasse geschrieben deren Grundlage std::ofstream ist.
    Ich hab als template den Operator << definiert um alles direkt nach std::ofstream zu schicken.
    Hab außerdem noch einen Operator << überladen um Zeichenketten abzufangen und '\n' durch "<br>\n" zu ersetzen
    Jetzt wollte ich noch endl abfangen können um es durch "<br>\n" zu ersetzen, aber ich komme einfach nicht dahinter was das für einen Typ hat 😞

    Ich wäre froh wenn jemand von euch einen Rat hätte 🙂
    Oder noch besser ein bisschen nützlichen Code 😉



  • hi!
    das problem ist, dass std::endl nicht einfach etwas ist, das in den ausgabestream geschoben wird, sondern etwas, das bestimmte operationen auf dem ausgabestream durchführt. die deklaration sieht so aus:

    template <class CharT, class Traits>
    basic_ostream<CharT, Traits>& endl (basic_ostream<CharT, Traits>& os)
    

    wenn du für deine klasse nun den passenden operator<< überladen willst, könntest du folgendes probieren:

    struct MyStream
    {
       friend MyStream& operator << (MyStream& ms, ostream& (*some_fun) (ostream&))
       {
         //...
         return ms;
       }
    };
    
    MyStream ms;
    ms << endl;
    

    das problem ist nur, dass endl nicht die einzige funktion mit dieser signatur ist. ends und flush gibt es ja auch noch.
    wenn du ganz schlau bist, könntest du auf die idee kommen, innerhalb des operators die adressen der funktionen zu vergleichen:

    #include <iostream>
    using namespace std;
    
    struct MyStream
    {
       friend MyStream& operator << (MyStream& ms, ostream& (*some_fun) (ostream&))
       {
          if (some_fun == static_cast<ostream&(*)(ostream&)>(endl))
          {
             //...
          }
          return ms;
       }
    };
    

    das ist allerdings ein bisschen hässlich.

    meiner meinung nach hast du zwei optionen:
    1. du vergisst dein design und machst deine logbuchklasse kompatibel zu den standardstreams (eventuell einfach nur als streambuf)
    2. du entwirfst deine eigene version von endl und konsorten:

    struct MyStream
    {
       friend MyStream& operator << (MyStream& ms, MyStream& (*fun) (MyStream&))
       {
          return fun(ms);
       }
    };
    
    MyStream& my_endl (MyStream& ms)
    {
       ms << '\n';
       ms.flush();
       return ms;
    }
    
    //...
    MyStream ms;
    ms << my_endl;
    


  • Danke! 🙂
    Sieht jetzt so aus:

    MyLog & MyLog::operator<<(ostream& (*i) (ostream&))
    {
    	if(i!=endl)
    		(*pLogFileStream)<<i;
    	else
    		(*pLogFileStream)<<"<br>"<<endl;
    	return(*this);
    }
    

Anmelden zum Antworten