cout überladen?



  • Hallo zusammen,

    folgendes Problem:
    Ich möchte wenn ein bestimmtes Präprozessor-Flag gesetzt ist, cout nur unter einer gewissen Bedingung ausführen.
    Könnte man zum Beispiel so erreichen:

    #ifdef foo
    if (bla) 
    {
    #endif
       cout<<"blup";
    #ifdef foo
    }
    #endif
    

    Nun kommt das aber im code relativ häufig vor, und obiges ist natürlich extrem unschön.
    Deshalb die Idee cout für denn fall wo foo gesetzt ist zu überladen.

    Mein Versuch:

    class my_ostream
    {
    public:
    	my_ostream(std::ostream& os, int bla)
    		: os(os)
    	{
    		active = (bla == 0);
    	}
    
    	template <class T>
    	my_ostream& operator<<(const T& val)
    	{
    		if (active) os<<val;
    		return *this;
    	}
    
    protected:
    	std::ostream& os;
    	bool active;
    };
    
    class my_cout : public my_ostream
    {
    public:
    	my_cout(int bla)
    		: my_ostream(std::cout, bla) {}
    };
    

    und dann wo benötigt instanziert:

    #ifdef foo
    my_cout cout(0);
    #endif
    
    cout<<"Hello World!";
    

    Leider bekomme ich den Fehler "no match for ‘operator<<’ in ... operator<<".
    Was mache ich falsch?
    Oder hat jemand eine elegantere Lösung für das angegebene Problem?
    (macros will ich eigentlich vermeiden)



  • C14 schrieb:

    Oder hat jemand eine elegantere Lösung für das angegebene Problem?
    (macros will ich eigentlich vermeiden)

    Makros sind okay für bedingte Kompilierung, aber eleganter gehts trotzdem.

    #ifdef FLAG // dein Präprozessor-Flag, das gesetzt sein muss
     #define OUTPUT(TEXT) std::cout << TEXT << std::endl
    #else      
     #define OUTPUT(TEXT)
    #endif
    

    So kannst du in deinem Code immer bequem OUTPUT verwenden, und über einen Präprozessorschalter (hier FLAG ) die Ausgabe ein-/ausschalten. Zum Beispiel:

    OUTPUT("Dieser Text wird nur im Geheim-Modus ausgegeben");
    


  • Wir hatten vor kurzem einen Thread zum Umlenken von cout. Das könntest du nutzen um mit dem #ifdef an einer einzelnen Stelle cout umzuleiten oder eben nicht. Oder du machst dir einen eigenen Stream, den du je nach flag entweder nach cout oder ins Nirvana leitest.



  • Hm, ich habe wohl das Problem etwas falsch verstanden und dachte, es ginge um spezifische Ausgaben, nicht std::cout allgemein.

    Hier ein Thread dazu:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-249387.html



  • makro gut.

    eventuallycout<<"md5: "<<md5(foofile)<<'\n';
    eventuallycout<<"eltc: "evenlongertocalc()<<'\n';
    


  • Ich finde ein Makro auch gut geeignet. Am besten schreibt man es so, dass man auch nicht für die Formatierung bezahlt, wenn die Ausgabe abgeschaltet wird.

    @volkard: eventuallycout scheint mir ein eher ungeeigneter Name zu sein -- eventually heißt jedenfalls nicht eventuell.



  • @volkard: so einfach gehts nicht, weil ich ja noch das if(bla) dastehen habe,
    das moechte ich nicht ins makro reinpacken, da bla nen ausdruck ist.

    (es geht konkret darum, bei nem parallelen programm nur den master prozess reden zu lassen)

    das mit dem streambuffer umleiten klingt interessant, das schau ich mir mal genauer an.



  • Was ist bla , irgendeine boolsche Bedingung?

    Geht trotzdem:

    #ifdef FLAG
     #define OUTPUT(TEXT, CONDITION) if (CONDITION) std::cout << TEXT << std::endl
    #else      
     #define OUTPUT(TEXT, CONDITION)
    #endif
    

    Allerdings könnte man sich dann so langsam eine Funktion überlegen, auf die das Makro umleitet:

    void output(const char* str, bool condition)
    {
        if (condition)
            std::cout << str << std::endl;
    }
    


  • makro gut.

    if(filesize==1048576){
       only_master_is_talking_cout<<"md5: "<<md5(foofile)<<'\n';
       only_master_is_talking_cout<<"eltc: "<<evenlongertocalc()<<'\n';
    }
    


  • Jester schrieb:

    @volkard: eventuallycout scheint mir ein eher ungeeigneter Name zu sein -- eventually heißt jedenfalls nicht eventuell.

    oh, ein false friends. danke.



  • makro ist schlecht:

    Die Bedingung ist eben, dass der aktuelle Prozess der Master ist:

    int rank;
    MPI_Comm_rank(comm, &rank);
    if (rank == 0)
      cout<<"bla";
    

    das sollte aber nicht bei jedem Aufruf von cout überprüft werden, sondern nur einmal.

    PS:
    also im Ganzen:

    #ifdef parallel
    int rank;
    MPI_Comm_rank(comm, &rank);
    if (rank == 0)
    #endif
      cout<<"bla";
    

    wollte euch nur nicht mit dem parallel-Kram verschrecken 😉



  • C14 schrieb:

    #ifdef parallel
    int rank;
    MPI_Comm_rank(comm, &rank);
    if (rank == 0)
    #endif
      cout<<"bla";
    

    wollte euch nur nicht mit dem parallel-Kram verschrecken 😉

    ist aber nötig, das ganze zu zeigen, sonst kommen wir nicht dahinter, wo deine ressentiments stecken.

    vorschlag A:

    bool isMaster(){
      int rank;
      MPI_Comm_rank(comm, &rank);
      return rank==0;
    }
    #ifdef parallel
      #define PRINT_IF_PARALLEL_MASTER(x) if(isMaster()) cout<<x;
    #esle
      #define PRINT_IF_PARALLEL_MASTER(x)
    #endif
    
    PRINT_IF_PARALLEL_MASTER("cout"<<lahmeFunktion());
    

    im nichtparallelfall wird kein MPI_Comm_rank aufgerufen und auch nicht die lahmeFunktion.
    im parallelfall wird immer MPI_Comm_rank aufgerufen.

    falls sich der master nicht verabschiedet, ich weiß ja nicht, wie die verwaltung ist, und falls das master-sein-testen lahm ist, kann man das auch noch cachen.
    vorschlag B:

    bool isMaster(){
      int rank;
      MPI_Comm_rank(comm, &rank);
      return rank==0;
    }
    bool cachedIsMaster(){
      static bool rersult=isMaster();
      return result;
    }
    #ifdef parallel
      #define PRINT_IF_PARALLEL_MASTER(x) if(isCachedMaster()) cout<<x;
    #esle
      #define PRINT_IF_PARALLEL_MASTER(x)
    #endif
    
    PRINT_IF_PARALLEL_MASTER("cout"<<lahmeFunktion());
    

    uups. das bewirkt ja was anderes. glaube, so bin ich an deinem code dran:

    #ifdef parallel
      #define PRINT_IF_NOT_PARALLEL_CLIENT(x) if(!isCachedMaster()) cout<<x;
    #esle
      #define PRINT_IF_NOT_PARALLEL_CLIENT(x) cout<<x;
    #endif
    
    PRINT_IF_NOT_PARALLEL_CLIENT("test"<<lahmeFunktion());
    

    aber eigentlich ist es glaub ich so:

    #ifdef parallel
       inline bool wantPrint(){return isMaster();}
    #esle
       inline bool wantPrint(){return true;}
    #endif
    

Log in to reply