Boost logo

Boost :

From: Csaba Szepesvari (szepes_at_[hidden])
Date: 1999-08-21 10:09:37


James Curran/MVP wrote:

> From: Reid Sweatman <reids_at_[hidden]>
>
> >class foo
> >{
> >public:
> > foo(value_type& T = nValue,bool initialise = false)
> >{ if(initialize) Initialize(T); }
> >};
>
> Am I missing something? I don't see that working as expected...
> Consider the simplified:
>
> class foo
> {
> int n;
> public:
> foo(int N = 5,bool initialise = false)
> { if(initialize) n = N; }
> };
>
> Now, Case #1
> Written: Foo X;
> Effective: foo X(5,false);
> Effect: X.n is not initialized.
>
> Case #2
> Written: foo X(7)
> Effective: foo X(7, false);
> Effect: X.n is not initialized.
>
> Case #3
> Written: foo X(7, true);
> Effective: same
> Effect: X.n is initialized to 7.
>
> Case #4
> Written: foo X(, true);
> Effective: foo X(5, true); // almost....
> Effect: X.n would be initialized to 5, if it weren't a syntax error.
>
> So, it would seem, that the only place where the default for the
> second-to-last parameter could be used it, is an error. Furthermore, the
> effect of case #2 is counter-intuitive.

You could change the initialization argument to a template argument as I
proposed before and then things would work as one would expect them to work.
However, I have to agree with Reid (see his earlier mail) that having just
two constructors, one without any parameters (and doing no initialization)
and one with a parameter used in the initialization would do the job. If you
have an idea of how to initialize your class you could add a third
constructor that would do the initialization with the default value. This
third constructor would have an enum parameter (just to differentiate this
constructor from the others):
class foo
{
public:
  ...
  typedef enum { init_with_default } Init_with_default;
  foo( Init_with_default ) { Initialize(); }
};
and
foo f(init_with_default);
would then do the job.

But the main reason of writing this letter is to let me make the observation
that normally you initialize vectors by passing a constructed object to the
vector constructor:

std::vector<foo> foovector( 10, foo(5) );

- this means copy construction which may be as efficient as direct
initialization (but this depends on many factors including the actual
implementation of the default allocator of the vector). So for vectors things
are nice and simple.

What you cannot do in this way is to have an initialized array of foos:

foo* fooarray = new foo[5];

- for this you would need a default constructor that is doing the
initialization (i.e. an initialization constructor is not sufficient here).
I don't see any way to have a class from which I could create both
initialized and unitialized arrays: there is only one default constructor and
it can only do one thing (either initize or don't initialize).
You could make the whole class a template with a bool parameter denoting if
initialization is needed - this seems to be the only way to overcome this
problem, e.g.
template <bool init =
true_if_you_like_default_initialization_otherwise_false>
class foo
{
public:
    foo() { if (init) Initialize(); }
};
then you could have all versions:
foo<>* fooarray1 = new foo<>[5];
foo<true>* fooarray1 = new foo<true>[5];
foo<false>* fooarray1 = new foo<false>[5];

but probably this has an unacceptably high price: the initialized and
unitialized versions of foo are actually different classes! You would need
quite an amount of work to make them equivalent.
Now comes the idea that having two classes allows one two have to default
constructors and a clever derivation may actually solve the problem:
class foo
{
public:
  foo() { };
  ..
};
class foo_init : public foo
{
public:
  foo_init() { Initalize(); }
  ..
};
(obviously, the other way around, having foo_init as the base class won't
work for obvious reasons).
Then you are allowed to write:

 foo* fnarray = new foo[5];
 foo* fnarray2 = new foo_init[5];

- perhaps a bit strange piece of code, but works. The price is minimal (for
simple classes).
But anyway, I think that all these are two complicated and using vectors is a
better way to solve the "initialize or not to initialize dilemma".

- Csaba


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk