class conditional initialization question

Z

zl2k

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
 
R

red floyd

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);
}
 
G

Goran

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.
 
S

SG

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.
 
V

Vladimir Jovic

SG said:
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
 
K

Kai-Uwe Bux

Goran said:
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
 
G

Goran

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.
 
V

Victor Bazarov

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
 
S

SG

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
 
V

Victor Bazarov

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,189
Members
46,735
Latest member
HikmatRamazanov

Latest Threads

Top