Boost logo

Boost :

From: David Abrahams (david.abrahams_at_[hidden])
Date: 2002-03-07 13:36:17


----- Original Message -----
From: "Howard Hinnant" <hinnant_at_[hidden]>

> Initialization is mandatory for std::complex and std::vector. :-\

Yes, but that's my point: the builtins aren't the problem here.

> Agreed initialization isn't always mandated in C++. Thank goodness.
> Else we wouldn't even have the chance to work our way out of this
> problem.

Yep.

> > Hmm, I'm unconvinced. If you're trying to write generic code, I
don't
> > think you should have to write this just to call a function with a
> > default-constructed value:
> >
> > template <class T, void (*f)(T), bool is_scalar =
> > boost::is_scalar<T>::value>
> > struct call_with_default_constructed
> > {
> > static void execute() { f(T()); }
> > };
> >
> > template <class T, void (*f)(T)>
> > struct call_with_default_constructed<T,f,true>
> > {
> > static void execute() { f(T(0)); }
> > }
> >
> > And you'd need a combinatoric suite of these just to make it work
for
> > multiple arguments.
>
> A std::function could've come to the rescue for this use:
>
> namespace std
> {
>
> namespace detail
> {
>
> template <class T>
> inline
> T
> default_value(int2type<true>) // is scalar
> {
> return T(0);
> }
>
> template <class T>
> inline
> T
> default_value(int2type<false>) // is not scalar
> {
> return T();
> }
>
> } // detail
>
> template <class T>
> inline
> T
> default_value()
> {
> return detail::default_value<T>(int2type<is_scalar<T>::value>());
> }
>
> } // std
>
> Now in your generic code you can:
>
> f(std::default_value<T>(), std::default_value<U>());

Of course I was proposing the converse of this, and you can implement it
without any language changes, and it doesn't open the door to undefined
behavior all over the language the way having T() uninitialized would:

template <class T>
inline T uninitialized_value(int2type<false>) // is not scalar
{
    T x; // undefined behavior, if you really demand it
    return x;
}

And it helps with efficiency, provided your compiler is smart enough to
optimize away the copy.
The big problem, of course, is that it still invokes undefined behavior.

If containers had an interface which took a number of elements and an
inplace-constructor function or function object, we could handle the
issue straightforwardly. It's too bad there's no way to capture
"function which constructs a T at this address" in static type info.

-Dave


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