Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2004-02-11 11:51:05


"Peter Dimov" <pdimov_at_[hidden]> writes:

> David Abrahams wrote:
>>
>> OK, so 8.5.3/5 says:
>>
>> A temporary of type ``cv1 T2'' [sic] is created, and a constructor
>> is called to copy the entire rvalue object into the temporary. The
>> reference is bound to the temporary or to a sub-object within the
>> temporary.*
>>
>> [Footnote: Clearly, if the reference initialization being processed
>> is one for the first argument of a copy constructor call, an
>> implementation must eventually choose the first alternative (binding
>> without copying) to avoid infinite recursion. --- end foonote]
>>
>> The constructor that would be used to make the copy shall be
>> callable whether or not the copy is actually done.
>>
>> The problem here is, IIUC, that the implementors read that as saying
>> that, because "a constructor is called to copy..." that the
>> constructor used must be a copy constructor?
>>
>> I don't understand why the converting constructor fails to be
>> considered when the templated SFINAE'd constructor *will* be used to
>> copy const lvalues. Templated constructors are never "copy ctors"
>> either, IIUC.
>
> It's a fine specimen of circular logic.
>
> The compiler is allowed to elide a temporary created by a copy
> constructor.
>
> The compiler is _not_ allowed to elide a temporary created by some
> other constructor, because this changes observable behavior and is
> not explicitly allowed.

I think what's explicitly allowed depends on your reading of 8.5.3/5

> The only copy constructor that can create a const temporary from an
> rvalue is X::X(X const &) (default arguments and ellipsis aside.)
>
> Therefore, once the compiler has decided to elide the temporary, it
> only needs to check for X(X const &). If such a constructor does not
> exist or is inaccessible, the elision of the temporary is illegal.

Well, I understand that as a philosophy, but I don't see it in the
standard. I also don't see any circle ;-)

> This behavior is perfectly safe and reasonable, _provided that_ the
> auto_ptr loophole does not exist. It was never intended to
> exist. Everything that is based on it goes against the core logic of
> the language.
>
> Does it make sense?

I guess so. I still don't know what the loophole is. I knew once,
but that knowledge is ghostly and flits away quickly.

> Once we are on the topic. As I understand it, 8.5.3 is intended to
> allow compilers to place ROM-able temporaries in ROM. Consider:
>
> void f(int const & x);
>
> int main()
> {
> f(5);
> }
>
> The compiler can place a temporary of type "int const" and value 5 in ROM,
> and pass its address to f. Similarly, in:
>
> struct X
> {
> int i;
> X(int i): i(i) {}
> };
>
> void f(X const & x);
>
> int main()
> {
> f( X(5) );
> }
>
> the compiler is allowed to construct a "X const" with a value of X(5) at
> compile time and place it in ROM.

OK. Relevance?

-- 
Dave Abrahams
Boost Consulting
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