Boost logo

Boost :

From: David Abrahams (david.abrahams_at_[hidden])
Date: 2002-03-06 19:40:40


[Howard, please see the end of the message]
----- Original Message -----
From: "Ralf W. Grosse-Kunstleve" <rwgk_at_[hidden]>

> Given these overloads:
>
> vector(size_t n, const T& x);
>
> template <class U>
> vector(size_t n, U const& u);
>
> template <class Iterator>
> vector(Iterator i1, Iterator i2);
>
> Consider:
>
> int a = 3;
> int b = 4;
> vector<size_t> v(a, b);
>
> Are you certain that the rules for overload resolution and type
> deduction are robust enough to resolve this as expected (and
> without driving the implementor crazy)?

Well, that's what I was referring to in my previous message (and the
sanity of the implementor has never been a consideration ;-P), but I'm
pretty sure it actually works. Implementors already need to handle the
existing constructors for vector<size_t>. The problem (and the
solutions) are well-known.

> > It could, but it would require that the container implementor
specialize
> > the constructors for the case where the container's value_type is
POD
> > and the Iterator's value_type is uninitialized. However, this is
> > aesthetically preferable from a standards POV, I believe: the
> > optimization is available but up to QOI.
>
> Sounds OK to me. However, I would argue that the constructor
>
> vector(size_t n, uninitialized);
>
> (where uninitialized is a typename) is much more intuitive.

That's not legal syntax. You can't pass a typename as a function
argument.

> It is not easy to realize that
>
> template <class U> vector(size_t n, U const& u);
>
> is not so much designed for "initialization with type conversion" but
> for "instantiation without initialization of the data."

I think you're viewing it from the wrong angle. The way I see it, it's
using a a conversion from uninitialized to complex<> when U ==
uninitialized. That just happens not to initialize the members.

However, as I indicated before it's not clear that deferred conversion
is desirable in all cases. I guess it also allows the conversion in the
case where T only has an /explicit/ conversion from U, though I think
it's possible to suppress that case.

> Eventually type
> traits are required anyway, so why not make the interface explicit?

I don't see what type traits have to do with it.

> Could we submit a proposal where we present both our views where
> they diverge?

I think it would be better to get some more input from others, first. I
think we could settle on a better solution than either of us have
proposed.

> P.S.: In some sense this issue is more pressing than the
> complex<T> question: complex<T> mostly works OK, there is
> just no promise that it will work on new platforms.

??? of course there is - the standard makes all kinds of promises that
it will work

But aren't you still dissatisfied with all of the issues of layout?

> But it is currently impossible to instantiate a std::vector
> without the initialization overhead.

Ultimately, I don't think you can/should locate the smarts in the
vector.
Checking whether the destructor is trivial is the wrong check:

int destroyed;
struct X
{
    X::~X() { ++destroyed; }
};

The right place to locate information about whether X can be constructed
in a particular way is in X, preferably in a constructor.

If we write:

struct complex
{
    complex(uninitialized) {}
    complex(double re, double imag) : real_(re), imag_(imag) {}
    double real_, imag_;
};

Then we can skip initialization by passing the right constructor
argument.

Even if you don't like the new templated vector constructor I proposed
(I don't think I like it), we can take advantage of a definition of
complex like the above one given the right iterator type.

I am getting another idea, that we need a way to pass (to any of the
container functions which accept an iterator range) an in-place
construction function object which avoids any copies. That would allow
the user to specify how the objects were to be constructed.

And a third idea: that this is what Howard's "move constructors" are
supposed to accomplish(?). If templated "converting move constructors"
were possible, it might help solve this problem, too (though I'm not
sure that it addresses the issue of the built-in types).

-Dave


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