Boost logo

Boost :

Subject: Re: [boost] [utility/value_init] boost::value_initialized<T> direct-initialized?
From: Fernando Cacciola (fernando.cacciola_at_[hidden])
Date: 2010-04-07 23:51:28


Hi People,

OK, only seven months after Eduard's inital request I finally made the time to
really look at it :)

Jeffrey Hellrung wrote:
> Niels Dekker - address until 2010-10-10 wrote:
>> Can anybody please have a look at the following feature request by
>> Edward Diener? https://svn.boost.org/trac/boost/ticket/3472 He
>> proposed to add an explicit constructor, value_initialized(T const&),
>> to boost::value_initialized<T>. This constructor would copy the value
>> of its argument to the object held by value_initialized<T>.
>>
OK, so as Niels quite clearly figured out, what Eduard wanted was this wrapper
to contain values either value or directrly initialized.

>> When such a constructor would be added, an object held by
>> value_initialized<T> might no longer be value-initialized. Instead it
>> might be direct-initialized.

Indeed.

>> Does anybody have any moral (?)
>> objections against the idea that value_initialized<T> might hold a
>> non-value-initialized object?
>>
A reasonable objection would be that a new comer would rightly question: why is
it called "value_" then, when in effect I'm direct-initializing it instead in
this case here?

Of course, a quick answer would be that the class guarantess value
initialization only when there is none, logicaly, and that the name is really
short for value_or_direct_initialized.

>> Personally I think it would be useful to allow the wrapped object to
>> be direct-initialized. But I do think there's a small risk that the
>> new explicit constructor might cause ambiguities in legacy user code.

I followed ALL of the MSVC bug reports, threads, even related CCW issues, and I
fail to see how in OUR case here there could be any ambiguity?

The MSVC (and GCC) bugs all boils down to a resolution mistake rooted on certain
"constructors that copy" in the base class.

These bugs are not about a mistaken ambiguity, which would turn a legal program
into ill-formed, forcing the programmer to change it, but about a wrong
selection, whose consequences are quite different.. so let's see:

None of these bugs reported show up when the choices are (a) the copy
constructor and (b) a **non-template** explicit constructor, as in our case.
So, I don't see why would we have to expect that to happen here.
But even if a compiler would get it wrong, as in those bugs, and called the
wrong ctor, the net effect would nevertheless be the same in our very specific
case (the worst that could happen is an extra temporary surely ellided anyway).

On the other front, regarding Neil's other sources of ambiguity... well,
honestly, if a user writes such code, I'm more than happy to put him out his
missery by not letting him compile such a mounstrocity anymore :)

Or can you come up with a less aritificial and contorted used case that could
result in ambiguity?

>> Therefor I suggested adding an extra "tag" parameter to the new
>> constructor, of a new type, boost::direct_initialized_t:
>>
>> struct direct_initialized_t { };
>> value_initialized(T const&, direct_initialized_t)
>>
>> Does anyone else also think that's a good idea? Or does anyone prefer
>> the explicit value_initialized(T const&) constructor originally
>> proposed by Edward?
>>
I'm not religiously against the additional parameter, but I definitely wouldn't
like it for no reason, and after all the analysis about what could effectively
happen, I don't see any reason for complicating it. So I'd go for Eduard's patch.

>> See also the thread starting at:
>> "Re: [boost] Transfer of Maintenance Rights (utility/value_init)"
>> http://lists.boost.org/Archives/boost/2010/03/164125.php
>>
>> Kind regards,
>>
>> Niels
>
> Is defining a new template class (e.g., value_or_direct_initialized<T>,
> or whatever) out of the question? Just a suggestion, and not confident
> it's a good one...
>

OTOH, there is a new angle here...

Having said that I'm more than happy with an extended value_initialized<> that
accepts direct initialization via a straightforward ctor, it *could* be argued
that having both initialized and value_initialized makes sense all by itself.

But let's see:

I can imagine myself explaining that "initialize<T> m(v)" does
direct-initialization, then that, OTOH, "initialized<T> m;" does
value-initialization, since there is no explicit initialization in this case.

Newcomers would say "OK, I follow".

Then I would proceed and explain that, "value_initialized<T> m" is also doing
value-initialization... What? why would I ever want to use that one then,
having the other??

And then I would answer: hmmm, right, you don't.

So the slipts ends up being just to prevent user code to break when we add the
feature...

Since I don't really see user code being broken here, this split makes no sense
to me.

What would have made sense is to have called this "initialized" to begin with,
and feature it with direct-initialization super powers! But adding this *now*
and leave its old ancestor for the elder? don't like it.

So, let's just add the plain and simple explicit ctor :)

[Neils, feel free to argue back :)

Best

--
Fernando Cacciola
SciSoft Consulting, Founder
http://www.scisoft-consulting.com

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