Boost logo

Boost :

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


I was assuming T was a given type:

struct T : addable<T>
{
    // ...
}

But I did some testing, and looks like the above code which normally should
fail if operator+ returned a lvalue reference actually works with rvalues:

struct T : boost::addable<T>
{
T(void)
{
std::cout << "T(): " << this << std::endl;
 }

T(const T &val)
{
std::cout << "T(const T&): " << this << std::endl;
 }

T(T &&val)
{
std::cout << "T(T&&): " << this << std::endl;
 }

~T(void)
{
std::cout << "~T(): " << this << std::endl;
 }

T& operator +=(const T& op)
{
 std::cout << this << " += " << &op << std::endl;
return *this;
 }
T& operator =(const T& op)
{
std::cout << this << " = const & " << &op << std::endl;
 return *this;
}

T& operator =(T&& op)
 {
std::cout << this << " = && " << &op << std::endl;
return *this;
 }
};

Output using VS2012 (displayed output in debug mode, but similar results
occur in release mode):

T &result = t1 + t2 + t3;

T(): 0040FEDB
T(): 0040FECF
T(): 0040FEC3
T(const T&): 0040FCD7
0040FCD7 += 0040FECF
T(T&&): 0040FEAB
~T(): 0040FCD7
0040FEAB += 0040FEC3

&result = 0040FEAB

T result = t1 + t2 + t3;

T(): 0035F9FF
T(): 0035F9F3
T(): 0035F9E7
T(const T&): 0035F7FB
0035F7FB += 0035F9F3
T(T&&): 0035F90F
~T(): 0035F7FB
0035F90F += 0035F9E7
T(T&&): 0035F9DB
~T(): 0035F90F

&result = 0035F9DB

Is this just MS trying to be "clever", or are these results
standard-compliant (and equally important, viable on all other rvalue-ref
aware compilers)? If this is indeed expected behavior, then there shouldn't
be any fuss over unsafe behavior at all, and the 4-overload version can be
used without any problems (assuming we didn't miss any corner cases).

On Wed, Apr 24, 2013 at 3:41 PM, Jeffrey Lee Hellrung, Jr. <
jeffrey.hellrung_at_[hidden]> wrote:

> On Wed, Apr 24, 2013 at 1:36 PM, Andrew Ho <helloworld922_at_[hidden]>
> wrote:
>
> > > Remind me how the 4-overload-version is unsafe, again?
> >
> > There's the potential for a user to assign a reference variable to an
> > invalid temporary:
> >
> > T &var = a + b + c;
> >
>
> Does operator+ return by value or by reference? If it returns by value, how
> is the above possible? Is T a typedef or template parameter for a
> const-qualified type in your example above?
>
> I am of the opinion this is a usage error (as is Daniel), but
> > none-the-less, was previously valid because the operators returned by
> > value.
>
>
> Okay, now I'm really confused. I would think return-by-reference would
> allow the above, but return-by-value would not.
>
> And how is this related to whether operator+'s parameters are by-value (1
> overload) or by-reference (4 overloads)? I mean, other than the former
> precluding return-by-reference, of course.
>
> Just as large a problem is that if this error does occur in real
> > code (old or new), it can be difficult to identify.
> >
> > > A macro which globally switches the effect of all uses of
> > Boost.Operators?
> > > Let's avoid that.
> >
> > We will need at least the compiler feature check switch since rvalue
> > references will cause compilers which don't support the feature fail.
>
>
> Yeah, that's fine; you're switching on compiler features, and you're
> switching to an objectively better implementation.
>
> Having a macro that switches *all* uses of Boost.Operators to either "safe"
> or "fast" (whatever those mean) implies that you can't mix safe uses with
> fast uses.
>
> After
> > a little digging, the commutative operators will always need special
> > handling since they directly use rvalue refs.
> >
> >
> >
> > On Wed, Apr 24, 2013 at 11:04 AM, Jeffrey Lee Hellrung, Jr. <
> > jeffrey.hellrung_at_[hidden]> wrote:
> >
> > > On Tue, Apr 23, 2013 at 11:06 PM, Andrew Ho <helloworld922_at_[hidden]>
> > > wrote:
> > >
> > > > Here's a thought about the direct use of r-value references vs. pass
> by
> > > > value
> > > > argument:
> > > >
> > > > We are planning on providing a version which is supposed to support
> > > > compilers
> > > > without move semantics. However, these implementations are close to,
> > > > perhaps
> > > > even exactly identical to the code that would take advantage of move
> > > > semantics
> > > > via pass by value.
> > > >
> > > > Say we allowed a user-accessible define which would allow the
> > programmer
> > > to
> > > > decide?
> > > >
> > >
> > > A macro which globally switches the effect of all uses of
> > Boost.Operators?
> > > Let's avoid that.
> > >
> > > something like:
> > > >
> > > > // BOOST_HAS_RVALUE_REFS is a feature availability check
> > > > // BOOST_UNSAFE_MOVE is user-definable override to use faster, unsafe
> > > > version
> > > > #if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_UNSAFE_MOVE)
> > > > // use 4 overload version
> > > > #else
> > > > // use pass-by-value version
> > > > #endif
> > > >
> > > > If the user is more concerned with safety over micro-optimizations,
> the
> > > > default behavior would resort to pass by value (good for backwards
> > > > compatibility).
> > > >
> > >
> > > Remind me how the 4-overload-version is unsafe, again?
> > >
> > > However, the user would have the option available to easily use the
> > faster
> > > > version if they deem it necessary.
> > > >
> > >
> > > - Jeff
> > >
> > > _______________________________________________
> > > Unsubscribe & other changes:
> > > http://lists.boost.org/mailman/listinfo.cgi/boost
> > >
> >
> >
> >
> > --
> > Andrew Ho
> >
> > _______________________________________________
> > Unsubscribe & other changes:
> > http://lists.boost.org/mailman/listinfo.cgi/boost
> >
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>

-- 
Andrew Ho

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