Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2004-04-17 06:10:00


"Andrea Torsello" <torsello_at_[hidden]> writes:

> Correct me if I am wrong, but if both behaviour could be interpreted
> as correct based on the current standard, it means that relying on one
> interpretation is undefine behaviour. At least untill a TC is issued.

Well, it's not undefined behavior. At best it's unspecified. IMO
with a careful reading of the standard, the interpretation taken by
Comeau is just wrong. What the standard says is really irrelevant,
though. What matters are the status quo today and what will happen in
the future. Today, compilers all act differently. In the future we
have the assurance of the CWG that my move example from N1610 will
work, via one of several possible routes.

By the way, if you are willing to give up on move semantics from
direct initialization, my technique will work in Comeau strict mode
just as well as yours. Nothing about what you did will get around
that problem; it seems to be a fact of current EDG compilers that in
strict mode direct initialization from an rvalue will only ever use an
ordinary (T const&) copy ctor.

The current version in the sandbox turns off the move optimization for
that case on current EDG in non-microsoft mode. If you're not
compiling in strict mode you can turn it back on with
-DBOOST_IMPLICIT_MOVE_CTOR_FOR_COPYABLE_TYPES. In fact, compilers in
general are good enough at copy elision that the move ctor
optimization only turns out to be useful for one other compiler I can
find: Intel 8.0 for Windows, where it works silently and is enabled by
default. I haven't tried /Za mode but apparently that's useless for
building real software on Windows.

> Besides it is not the only problem. I didn't just start to create my
> own version for pleasure. I started using your approach but the
> templated constructor had weird interactions with other 2 parameter
> constructors. I cannot remember the case off hand, but I will look for
> it and post it.

Please do. Also please use the latest version of the code in the
sandbox to test against.

>> There is never a need to pass a temporary by const ref if you can
>> move it.
>
> What if the user of the library wants to pass the object to a function
> that has that signature? One of the main goal is for the move
> infrastructure to be as transparent as possible.

I'm sorry I was unclear. My library allows you to pass a temporary
by const ref transparently. You said:

> Finally the need for X(X const &) to pass a temporary by const ref
> was the reason that forced Alexandrescu to add the special return
> type to mojo.

Actually I'm not sure what I was trying to say anymore. I can state
that my library already allows

  sink(source());

to work transparently with move semantics on all compilers I've
tested on.

>> Yes.
>> template <class T> enable_if_same<T const, X const, void> f(T&); //
>> lvalues
>> void f(move_from<X>); // temporaries
>
> Right, didn't realize that you could use the same trick here, good
> stuff! Anyway, using enable_if_same as a result type convertible to
> the required type

Sorry, that wans just a mistake; it isn't convertible to anything. I
meant:

      template <class T> // lvalues
      typename enable_if_same<T const, X const, void>::type f(T&);

      void f(move_from<X>); // temporaries

> Anyway forcing an otherwise non-templated fiunction to be templated,
> while not a real problem is not really optimal, especially
> considering the difficulty most compilers have with the export
> keyword. Of corse, the templated class might just delegate all work
> to a non templated class

Exactly. Or you could just use explicit instantiation. BTW I assume
you mean "templated function".

> , but still.

It's no worse a problem than replacing what should be a reference
paramter with another type that can be constructed by implicit
conversion. You still cut off the possibility of user-defined
conversions.

>> > The code snipped you sent on the quoted message doesn't appear to
>> > allow it, but as I said, I am not sure about newer versions.
>>
>> Why don't you do some research? It's all in the sandbox.
>
> I did

I meant "research into newer versions". If you had done that, you
could be sure of it.

If you run the latest tests with --verbose-test on the bjam
command-line, it will show you exactly what's allowed and how many
unneccessary copies are made with your compiler.

> , and I proposed an alternative which has some advantages and
> some disadvantages.

I don't see any advantages yet.

> If you like i,t please use it, if you don't, don't! I was looking
> for feedback and constructive criticism, not forcing my approach to
> anyone.

I didn't take it that way. I'm not arguing with you out of
defensiveness. If you really think what you did had some advantages,
I want to be convinced of them so I can change my library to be the
best possible.

>> I still don't understand why you think it's important to
>> distinguish const temporaries from const lvalues.
>
> As you said in another post, it is not a problem to move from a const
> temporary (the compiler might just copy the const temporary to a non
> const temporary and optimize the copy away), hece you want to move
> from const temporaries.

Which my library does.

> On the other hand, you should certainly not move from lvalues.

OK, but in that case I don't see why you want to distinguish const
temporaries from non-const temporaries.

-- 
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

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