Konstruktor aufruf mit bool Variablen



  • normaldenker schrieb:

    Jeder normaldenkende Programmierer würde das so umsetzen:
    [...]

    Haelst du es nicht fuer praktisch, dafuer noch einen neuen Thread zu starten, damit man parallel zum einlesen schon wieder was anderes machen kann?



  • Marthog schrieb:

    normaldenker schrieb:

    Jeder normaldenkende Programmierer würde das so umsetzen:[...]

    Haelst du es nicht fuer praktisch, dafuer noch einen neuen Thread zu starten, damit man parallel zum einlesen schon wieder was anderes machen kann?

    Nein, das wäre Overkill.



  • Was sollen "option1,2,3" sein? Gib ihnen Namen!

    struct Settings
    {
        enum printOption_e
        {
            NO_PRINT,
            PRINT   
        };
    
        enum saveOption_e
        {
            AUTO_SAVE,
            MANUAL_SAVE
        };
    
        enum alarmOption_e
        {
            SILENT,
            ALARMING
        };
    
        Settings( printOption_e po = NO_PRINT, saveOption_e so = AUTO_SAVE, alarmOption_e ao = SILENT )  
        : printOption( po )
        , saveOption( so )
        , alarmOption( ao )
        {}
    
        printOption_e printOption;
        saveOption_e saveOption;
        alarmOption_e alarmOption;
    };
    
    int main()
    {
        Foo( Settings( Settings::PRINT, Settings::MANUAL_SAVE, Settings::ALARMING ) );
    }
    

    ~Edit: alles in die Klasse (wg. namespace) II: 1. Vorschlag gelöscht, war eh Mist~



  • Wobei der gesamte Ansatz etwas seltsam ist: Warum die Optionen nicht gleich als Eigenschaften der Klasse Foo?
    Optionen werden oft einfach bit-weise kombiniert, z.B:

    struct Foo
    {
        enum options_e
        {
            NONE = 0,
            PRINTING = 1 << 0,
            SAVING   = 1 << 1,
            ALARMING = 1 << 2
        };
    
        Foo( unsigned int opt = NONE )  
        : options( opt )
        {}
    
    private:
        unsigned int options;
    };
    
    int main()
    {
        Foo( Foo::PRINTING | Foo::SAVING | Foo::ALARMING );
    }
    

    Etwas unschön ist, dass kombinierte Enum-Werte nicht mehr vom Enum-Typ sind, sondern (unsigned) int.

    Sind denn die Optionen der jeweiligen Foo-Instanz zur Compilezeit schon bekannt? Dann könnte man auch über Polymorphie oder Policy-Klassen nachdenken... Das macht dann die Auswertung der Optionen innerhalb von Foo eleganter.



  • aliB schrieb:

    Kann man den Aufruf lesbarer machen in C++?

    Da gibt es viele Möglichkeiten, einige wurden auch schon genannt. Hier eine weitere:

    struct Settings
    {
        struct Builder {
            explicit Builder(const Settings &s = Settings());
            Builder(const ::Builder &other);
            ~Builder() noexcept;
    
            Builder& operator=(const RequestBody::Builder &other);
    
            operator Builder() const;
    
            Builder& option1(bool state);
            Builder& option2(bool state);
            Builder& option3(bool state);
    
        private:
            struct Private;
            Private *d = nullptr;
        };
    
        Settings() : option1( false ),
                     option2( false ),
                     option3( false )
        {
        }
    
        friend Builder;
        bool option1;
        bool option2;
        bool option3;
    };
    
    struct Settings::Builder::Private {
        Private(const Settings &s) : settings s ) {}
    
        Settings settings;
    };
    
    Settings::Builder::Builder(const Settings &s)
      : d( new Private( s ) ) {
    }
    
    Settings::Builder::Builder(Settings::Builder const &other)
      : d( new Private( other.d->body ) ) {
    }
    
    Settings::Builder::~Builder() {
        delete d;
    }
    
    Settings::Builder& Settings::Builder::operator=(Settings::Builder const &other) {
        d->settings = other.d->settings;
        return *this;
    }
    
    Settings::Builder::operator Settings() const {
        return d->settings;
    }
    
    Settings::Builder& Settings::Builder::option1(bool state) {
        d->settings.option1 = state;
        return *this;
    }
    
    Settings::Builder& Settings::Builder::option1(bool state) {
        d->settings.option2 = state;
        return *this;
    }
    
    Settings::Builder& Settings::Builder::option3(bool state) {
        d->settings.option3 = state;
        return *this;
    }
    
    int main()
    {
        Settings s = Settings::Builder().option1( true ).option3( true );
    
        // Wenn du sprechendere Namen verwendest, wäre es noch lesbarer:
        //Url url = Url::Builder().schema( "http" ).host( "www.c-plusplus.net" ).port( 80 ).path( "/forum/posting" );
    }
    


  • enum { OPT1 = 0x1, OPT2 = 0x2, OPT3 = 0x4 };
    
    void Foo(int n){ /* ... */ }
    
    main(){
      Foo(OPT1 | OPT2 | OPT3);
    }
    

  • Mod

    minastaros schrieb:

    Etwas unschön ist, dass kombinierte Enum-Werte nicht mehr vom Enum-Typ sind, sondern (unsigned) int.

    Dafür gibts Operatorüberladung.



  • Hilefoks schrieb:

    Da gibt es viele Möglichkeiten, einige wurden auch schon genannt. Hier eine weitere:

    struct Settings
    {
        // Settings Klasse
        struct Builder {
            // eine weitere Klasse, die kein Mensch braucht, es aber viel umständlicher macht
    

    Und das soll besser sein? Ineffizient (überflüssige Allokation) und umständlich nur um 3 Optionen zu setzen. Vom Ansatz dennoch nicht ganz weit weg. Hier ist eine einfachere und effizientere Variante:

    class Settings
    {
      bool _option1;
      bool _option2;
      bool _option3;
    
    public:
      Settings()
        : _option1(false),
          _option2(false),
          _option3(false)
          { }
    
      Settings& option1(bool sw)   { _option1 = sw; return *this; }
      Settings& option2(bool sw)   { _option2 = sw; return *this; }
      Settings& option3(bool sw)   { _option3 = sw; return *this; }
      bool option1() const  { return _option1; }
      bool option2() const  { return _option2; }
      bool option3() const  { return _option3; }
    };
    
    int main(int argc, char* argv[])
    {
      Settings s = Settings().option1(true).option2(true).option3(true);
    
      // oder ein Beispiel sprechenden Namen:
      Settings s = Settings().schema( "http" ).host( "www.c-plusplus.net" ).port( 80 ).path( "/forum/posting" );
    }
    

    Der Code ist lesbarer und der syntaktische Zucker kann vom Compiler komplett weg optimiert werden.

    Man kann natürlich auch wahlweise die Member öffentlich machen und die getter weg lassen, wie im ersten Beispiel. Dann muss man sich nur sinnvolle Namen für die setter ausdenken, wie z.B. setOption1(bool) .



  • zur (weiteren) Info: dies nennt sich dann Named Parameter Idiom



  • tntnet schrieb:

    Vom Ansatz dennoch nicht ganz weit weg. Hier ist eine einfachere und effizientere Variante:

    class Settings
    {
      bool _option1;
      bool _option2;
      bool _option3;
    
    public:
      Settings()
        : _option1(false),
          _option2(false),
          _option3(false)
          { }
    
      Settings& option1(bool sw)   { _option1 = sw; return *this; }
      Settings& option2(bool sw)   { _option2 = sw; return *this; }
      Settings& option3(bool sw)   { _option3 = sw; return *this; }
      bool option1() const  { return _option1; }
      bool option2() const  { return _option2; }
      bool option3() const  { return _option3; }
    };
    
    int main(int argc, char* argv[])
    {
      Settings s = Settings().option1(true).option2(true).option3(true);
    
      // oder ein Beispiel sprechenden Namen:
      Settings s = Settings().schema( "http" ).host( "www.c-plusplus.net" ).port( 80 ).path( "/forum/posting" );
    }
    

    Der Code ist lesbarer [...]

    ähm ... der code ist einfacher und lesbarer als

    enum { OPT1 = 0x1, OPT2 = 0x2, OPT3 = 0x4 };
    Foo(OPT1 | OPT2 | OPT3);
    

    ??
    😮


Anmelden zum Antworten