Boost logo

Boost :

Subject: Re: [boost] [operators] The future of Boost.Operators
From: Andrew Ho (helloworld922_at_[hidden])
Date: 2013-04-25 15:24:03


> Maybe we're talking past each other. I have 3 overload set variants in
> mind:
>
> (A)
> T operator?(T, T);
>
> (B)
> T operator?(T const &, T const &);
> ...
> T operator?(T&&, T&&);
>
> (C)
> T operator?(T const &, T const &);
> ...
> T&& operator?(T&&, T&&);
>
> AFAICT, neither (A) nor (B) have any safety issues. Oh, but now I see the
> problem with (C): T&&'s are implicitly convertible to T&'s...that's what I
> was missing before. Sorry for being dense.
>
> So if you do
>
> T& a = b + c;
>

This succeeds in VS2012 with all (no compile or runtime problems, oddly
VS2012 extends the lifetime of ref returned by C to be valid), and fails
with all in gcc 4.7.2 (compiler error) :P

> invalid initialization of non-const reference of type 'T&' from type 'T&&'

Yep, this is what happens in gcc for me.

>
> I swear I just tried a T& y = static_cast<T&&>(x) on gcc and finding it
> compiled fine.

This gave a compiler error for me.

> Now you can ask the same question with T const& instead...

Compile succeeds, with only two operands the called overload returns a T,
not T&& so there's no problems.

If you had:

const T& r = a + b + c;

(A) and (B) are perfectly safe, but (C) will have runtime issues.

Same goes for:

T&& a = b + c;
T&& r = a + b + c;

First line doesn't have any problems with (A), (B), or (C) because of which
overload is used. The second line (A) and (B) have no problems but (C) will
have runtime issues.

Of course, (C) will have a few extra temporaries created (which may or may
not be optimized away). The question originally posed is do we:

1. Ignore this problem with (C) to get better performance and just document
the problem?
2. Implement (B) to take advantage of move semantics with no internal
problems, albeit with a few temporaries being created (if they aren't
optimized away by the compiler)?
3. Implement a user-accessible macro switch to let the user decide globally

As Jeff said, (3) is ugly especially when linking different codes together,
but does provide the most options to the user.

(2) isn't necessarily the most efficient but is completely safe. It may also
end up being just as efficient as (1) if compilers support the optimization
to remove unnecessary temporaries.

Daniel's argument is that the problems which occur with (C) are typically a
result of user error, and (C) in general guarantees the least amount of
temporaries being used. Are there any cases where the problems described
above with (C) would be a result of intended behavior with no acceptable
work-around?

Hopefully we're on the same page now.


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