class conditional initialization question

Discussion in 'C++' started by zl2k, Sep 23, 2010.

  1. zl2k

    zl2k Guest

    hi, there

    I have

    class Foo{
    explicit Foo(int a);
    explicit Foo(int a, int b);
    }

    how can I conditionally create an instance of Foo not using the
    pointer?

    I want something like

    Foo foo; // it's already initialized, do I need a dummy explicit Foo()
    in the Foo class?
    if (use1var){
    // initialize foo with 1 variable, how?
    }
    else{
    // initialize foo with 2 variable
    }
    // play with foo

    I can put //play with foo within the if else, but that will make the
    code too bulky.

    Thanks a lot.

    zl2k
     
    zl2k, Sep 23, 2010
    #1
    1. Advertising

  2. zl2k

    red floyd Guest

    On Sep 23, 3:27 pm, zl2k <> wrote:
    > hi, there
    >
    > I have
    >
    > class Foo{
    >     explicit Foo(int a);
    >     explicit Foo(int a, int b);
    >
    > }
    >
    > how can I conditionally create an instance of Foo not using the
    > pointer?
    >
    > I want something like
    >
    > Foo foo; // it's already initialized, do I need a dummy explicit Foo()
    > in the Foo class?
    > if (use1var){
    >   // initialize foo with 1 variable, how?}
    >
    > else{
    >   // initialize foo with 2 variable}
    >
    > // play with foo
    >
    > I can put //play with foo within the if else, but that will make the
    > code too bulky.
    >



    inline Foo create_foo(int use1var, int a, int b = 0)
    {
    return use1var ? Foo(a) : Foo(a,b);
    }
     
    red floyd, Sep 24, 2010
    #2
    1. Advertising

  3. zl2k

    Goran Guest

    On Sep 24, 1:23 am, red floyd <> wrote:
    > On Sep 23, 3:27 pm, zl2k <> wrote:
    >
    >
    >
    > > hi, there

    >
    > > I have

    >
    > > class Foo{
    > >     explicit Foo(int a);
    > >     explicit Foo(int a, int b);

    >
    > > }

    >
    > > how can I conditionally create an instance of Foo not using the
    > > pointer?

    >
    > > I want something like

    >
    > > Foo foo; // it's already initialized, do I need a dummy explicit Foo()
    > > in the Foo class?
    > > if (use1var){
    > >   // initialize foo with 1 variable, how?}

    >
    > > else{
    > >   // initialize foo with 2 variable}

    >
    > > // play with foo

    >
    > > I can put //play with foo within the if else, but that will make the
    > > code too bulky.

    >
    > inline Foo create_foo(int use1var, int a, int b = 0)
    > {
    >      return use1var ? Foo(a) : Foo(a,b);
    >
    > }
    >
    >


    Yes, but I think that requires that Foo is copy-constructible even if
    optimization elides copying. That's unfortunate in some use-cases. In
    that case I propose using (a slightly modified form of) swap idiom:

    class Foo
    {
    Foo(Foo& rhs); // Intentionally not const, swaps *this and rhs.
    // I call this "form" of a copy ctor constructor a "swaptor".
    // It could be that new C++0X standard calls it "move
    constructor" ;-).

    Foo(int);
    Foo(int, int);
    };

    inline Foo create_foo(int use1var, int a, int b = 0)
    {
    return use1var ? Foo(a) : Foo(a,b);
    }

    Goran.
     
    Goran, Sep 24, 2010
    #3
  4. zl2k

    SG Guest

    On 24 Sep., 00:27, zl2k wrote:
    >
    > I have
    >
    > class Foo{


    public:

    >     explicit Foo(int a);
    >     explicit Foo(int a, int b);
    > }
    >
    > how can I conditionally create an instance of Foo not using the
    > pointer?
    >
    > I want something like
    >
    > Foo foo; // it's already initialized, do I need a dummy explicit Foo()
    > in the Foo class?
    > if (use1var){
    >   // initialize foo with 1 variable, how?}
    > else{
    >   // initialize foo with 2 variable}


    }

    > // play with foo
    >
    > I can put //play with foo within the if else, but that will make the
    > code too bulky.


    You could write:

    Foo foo = use1var ? function1() : function2();
    // play with foo

    where function1 and function2 return a Foo object by value.
    Or, you could write:

    boost::scoped_ptr<Foo> pfoo;
    if (use1var) {
    pfoo.reset( new Foo(23,42) );
    } else {
    pfoo.reset( new Foo(1729) );
    }
    // play with *pfoo

    Or, you could write:

    boost::eek:ptional<Foo> ofoo = boost::none;
    if (use1var) {
    ofoo = Foo(23,42); // "copy initialization"
    } else {
    ofoo = Foo(1729); // "copy initialization"
    }
    // play with *ofoo

    Unfortunately boost::eek:ptional doesn't seem to allow an in-place
    construction. At least I don't see anything to that effect in the
    documentation.
     
    SG, Sep 24, 2010
    #4
  5. SG wrote:
    > On 24 Sep., 00:27, zl2k wrote:
    >> I have
    >>
    >> class Foo{

    >
    > public:
    >
    >> explicit Foo(int a);
    >> explicit Foo(int a, int b);
    >> }
    >>
    >> how can I conditionally create an instance of Foo not using the
    >> pointer?
    >>
    >> I want something like
    >>
    >> Foo foo; // it's already initialized, do I need a dummy explicit Foo()
    >> in the Foo class?
    >> if (use1var){
    >> // initialize foo with 1 variable, how?}
    >> else{
    >> // initialize foo with 2 variable}

    >
    > }
    >
    >> // play with foo
    >>
    >> I can put //play with foo within the if else, but that will make the
    >> code too bulky.

    >
    > You could write:
    >
    > Foo foo = use1var ? function1() : function2();
    > // play with foo
    >
    > where function1 and function2 return a Foo object by value.


    If the Foo's constructor takes one argument, you can return it from a
    function :
    Foo foo( GetArgument( uselvar ) );
    // use foo
     
    Vladimir Jovic, Sep 24, 2010
    #5
  6. zl2k

    Kai-Uwe Bux Guest

    Goran wrote:

    > On Sep 24, 1:23 am, red floyd <> wrote:
    >> On Sep 23, 3:27 pm, zl2k <> wrote:
    >>
    >>
    >>
    >> > hi, there

    >>
    >> > I have

    >>
    >> > class Foo{
    >> > explicit Foo(int a);
    >> > explicit Foo(int a, int b);

    >>
    >> > }

    >>
    >> > how can I conditionally create an instance of Foo not using the
    >> > pointer?

    >>
    >> > I want something like

    >>
    >> > Foo foo; // it's already initialized, do I need a dummy explicit Foo()
    >> > in the Foo class?
    >> > if (use1var){
    >> > // initialize foo with 1 variable, how?}

    >>
    >> > else{
    >> > // initialize foo with 2 variable}

    >>
    >> > // play with foo

    >>
    >> > I can put //play with foo within the if else, but that will make the
    >> > code too bulky.

    >>
    >> inline Foo create_foo(int use1var, int a, int b = 0)
    >> {
    >> return use1var ? Foo(a) : Foo(a,b);
    >>
    >> }
    >>
    >>

    >
    > Yes, but I think that requires that Foo is copy-constructible even if
    > optimization elides copying. That's unfortunate in some use-cases. In
    > that case I propose using (a slightly modified form of) swap idiom:
    >
    > class Foo
    > {
    > Foo(Foo& rhs); // Intentionally not const, swaps *this and rhs.
    > // I call this "form" of a copy ctor constructor a "swaptor".
    > // It could be that new C++0X standard calls it "move
    > constructor" ;-).
    >
    > Foo(int);
    > Foo(int, int);
    > };
    >
    > inline Foo create_foo(int use1var, int a, int b = 0)
    > {
    > return use1var ? Foo(a) : Foo(a,b);
    > }


    I have difficulties understanding your suggestion. How would you actually
    use it for the usecase of the OP?

    a) Foo foo ( create_foo( u, a, b ) );

    would not work to initialize foo: it would not compile as the temporary
    returned by create_foo() does not bind to the non-const reference argument
    of the swaptor.


    b) I also do not see how you avoid the copy-constructor. After all,
    create_foo() is _returning_ a Foo. At that point, the copy-constructor has
    to be visible, right?


    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Sep 24, 2010
    #6
  7. zl2k

    Goran Guest

    On Sep 24, 2:22 pm, Kai-Uwe Bux <> wrote:
    > Goran wrote:
    > > On Sep 24, 1:23 am, red floyd <> wrote:
    > >> On Sep 23, 3:27 pm, zl2k <> wrote:

    >
    > >> > hi, there

    >
    > >> > I have

    >
    > >> > class Foo{
    > >> > explicit Foo(int a);
    > >> > explicit Foo(int a, int b);

    >
    > >> > }

    >
    > >> > how can I conditionally create an instance of Foo not using the
    > >> > pointer?

    >
    > >> > I want something like

    >
    > >> > Foo foo; // it's already initialized, do I need a dummy explicit Foo()
    > >> > in the Foo class?
    > >> > if (use1var){
    > >> > // initialize foo with 1 variable, how?}

    >
    > >> > else{
    > >> > // initialize foo with 2 variable}

    >
    > >> > // play with foo

    >
    > >> > I can put //play with foo within the if else, but that will make the
    > >> > code too bulky.

    >
    > >> inline Foo create_foo(int use1var, int a, int b = 0)
    > >> {
    > >> return use1var ? Foo(a) : Foo(a,b);

    >
    > >> }

    >
    > > Yes, but I think that requires that Foo is copy-constructible even if
    > > optimization elides copying. That's unfortunate in some use-cases. In
    > > that case I propose using (a slightly modified form of) swap idiom:

    >
    > > class Foo
    > > {
    > >   Foo(Foo& rhs); // Intentionally not const, swaps *this and rhs.
    > >   // I call this "form" of a copy ctor constructor a "swaptor".
    > >   // It could be that new C++0X standard calls it "move
    > > constructor" ;-).

    >
    > >   Foo(int);
    > >   Foo(int, int);
    > > };

    >
    > > inline Foo create_foo(int use1var, int a, int b = 0)
    > > {
    > >   return use1var ? Foo(a) : Foo(a,b);
    > > }

    >
    > I have difficulties understanding your suggestion. How would you actually
    > use it for the usecase of the OP?


    In fact, only by using a compiler with nonstandard extensions to allow
    my thing to compile :-(. Sorry, folks!

    Goran.
     
    Goran, Sep 24, 2010
    #7
  8. On 9/23/2010 6:27 PM, zl2k wrote:
    > I have
    >
    > class Foo{
    > explicit Foo(int a);
    > explicit Foo(int a, int b);
    > }
    >
    > how can I conditionally create an instance of Foo not using the
    > pointer?
    >
    > I want something like
    >
    > Foo foo; // it's already initialized, do I need a dummy explicit Foo()
    > in the Foo class?
    > if (use1var){
    > // initialize foo with 1 variable, how?
    > }
    > else{
    > // initialize foo with 2 variable
    > }
    > // play with foo
    >
    > I can put //play with foo within the if else, but that will make the
    > code too bulky.


    Placement new, maybe. If your Foo class is going to have a default
    c-tor, then you can re-initialize the object using placement new
    technique, which is sometimes frowned upon, yet seems to work:

    #include <new>

    struct Foo {
    explicit Foo(int);
    explicit Foo(int,int);
    Foo();
    };

    int main(int argc, char argv[])
    {
    int a = 0, b = 1;

    Foo foo; // default-initalized object

    if (argc % 2) // your 'use1var'
    {
    foo.~Foo(); // destroy it first
    new (&foo) Foo(a); // now reconstruct it in-place
    }
    else
    {
    foo.~Foo(); // destroy it first
    new (&foo) Foo(a,b);
    }
    }

    // use foo here as you need

    There is sometimes a question whether we should destruct the object
    before using its memory to construct the new, and I'm on the side that
    says 'yes', as you might have guessed.

    So, the necessary condition is that your object is constructible in some
    other way, unless it's OK to construct it using one variable and then
    destroy it and reconstruct using two:

    #include <new>

    struct Foo {
    explicit Foo(int);
    explicit Foo(int,int);
    };

    int main(int argc, char argv[])
    {
    int a = 0, b = 1;

    Foo foo(a); // use one

    if (!(argc % 2)) // inverse to your condition
    {
    foo.~Foo(); // destroy it first
    new (&foo) Foo(a, b); // now reconstruct it in-place
    }
    }

    (and you could construct using two first, and then reconstruct using one
    if that's the preferred order).

    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Sep 24, 2010
    #8
  9. zl2k

    SG Guest

    On 24 Sep., 14:58, Victor Bazarov wrote:
    >
    > Placement new, maybe.


    Isn't boost::eek:ptional just an elegant way of encapsulating a placement
    new?

    > int main(int argc, char argv[])
    > {
    >     int a = 0, b = 1;
    >     Foo foo; // default-initalized object
    >     if (argc % 2) // your 'use1var'
    >     {
    >        foo.~Foo();        // destroy it first
    >        new (&foo) Foo(a);  // now reconstruct it in-place
    >     }
    >     else
    >     {
    >        foo.~Foo();        // destroy it first
    >        new (&foo) Foo(a,b);
    >     }
    > }


    Apart from some possible undefined behaviour problem (I'm not sure
    about the legality of manually destroying objects with automatic life-
    time) another problem would be exception safety. If Foo's constructor
    throws an exception, stack unwinding probably tries to destruct foo
    again, even though you've already destructed it.

    Cheers!
    SG
     
    SG, Sep 24, 2010
    #9
  10. On 9/24/2010 4:00 PM, SG wrote:
    > On 24 Sep., 14:58, Victor Bazarov wrote:
    >>
    >> Placement new, maybe.

    >
    > Isn't boost::eek:ptional just an elegant way of encapsulating a placement
    > new?


    I don't know boost. Haven't got a need to learn it.

    >> int main(int argc, char argv[])
    >> {
    >> int a = 0, b = 1;
    >> Foo foo; // default-initalized object
    >> if (argc % 2) // your 'use1var'
    >> {
    >> foo.~Foo(); // destroy it first
    >> new (&foo) Foo(a); // now reconstruct it in-place
    >> }
    >> else
    >> {
    >> foo.~Foo(); // destroy it first
    >> new (&foo) Foo(a,b);
    >> }
    >> }

    >
    > Apart from some possible undefined behaviour problem (I'm not sure
    > about the legality of manually destroying objects with automatic life-
    > time) another problem would be exception safety. If Foo's constructor
    > throws an exception, stack unwinding probably tries to destruct foo
    > again, even though you've already destructed it.


    Yes, there are problems. The new standard allows forwarding to other
    constructors, maybe there is a solution there...

    I wonder if eventually this syntax makes it into the language:

    Foo foo { use1var ? (a) : (a,b) };

    so the compiler creates code branching to different constructors based
    on the run-time value of 'use1var'... :)

    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Sep 24, 2010
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alec S.
    Replies:
    10
    Views:
    10,333
    Alec S.
    Apr 16, 2005
  2. JKop
    Replies:
    10
    Views:
    996
  3. Matthias Kaeppler
    Replies:
    2
    Views:
    471
    Victor Bazarov
    Jul 18, 2005
  4. Matthias Kaeppler

    Smart pointers: Conditional initialization

    Matthias Kaeppler, Nov 26, 2005, in forum: C++
    Replies:
    4
    Views:
    423
    Kaz Kylheku
    Nov 27, 2005
  5. Replies:
    6
    Views:
    485
    Ron Natalie
    Dec 11, 2005
Loading...

Share This Page