yamiez
yamiez

Reputation: 33

Returning reference using a ternery expression causes runtime error

For some reason, the second method will not work.

concurrency::event<void( event_data& ), codec_cvt> &get_event( const string_type &event )
{
        auto it = events_.find( event );
        if ( it == events_.end( ) )
            throw /* exception */;
        return *it->second;
}

However, this method using my preffered syntax is returning an address of a temporary. When it should be exactly, correct?

concurrency::event<void( event_data& ), codec_cvt> &get_event( const string_type &event )
{
    auto it = events_.find( event );
    return it != events_.end( ) ?
        *it->second :
        throw;
 }

Upvotes: 2

Views: 102

Answers (1)

T.C.
T.C.

Reputation: 137310

Before C++14, the standard provided that the result of an expression of the form false ? throw 1 : x is a copy of x rather than x itself (technically, it applies the lvalue-to-rvalue, array-to-pointer, and function-to-pointer conversions on x to yield a prvalue). N3337 [expr.cond]/2:

If either the second or the third operand has type void, then the lvalue-to-rvalue ([conv.lval]), array-to-pointer ([conv.array]), and function-to-pointer ([conv.func]) standard conversions are performed on the second and third operands, and one of the following shall hold:

  • The second or the third operand (but not both) is a throw-expression ([except.throw]); the result is of the type of the other and is a prvalue.
  • [...]

This was changed by Core issue 1560:

A glvalue appearing as one operand of a conditional-expression in which the other operand is a throw-expression is converted to a prvalue, regardless of how the conditional-expression is used:

[...]

This seems to be gratuitous and surprising.

and the paragraph now reads:

If either the second or the third operand has type void, one of the following shall hold:

  • The second or the third operand (but not both) is a (possibly parenthesized) throw-expression ([expr.throw]); the result is of the type and value category of the other. The conditional-expression is a bit-field if that operand is a bit-field.
  • [...]

MSVC simply hasn't gotten around to implementing the fix yet. Clang 3.5+ does have it implemented.

Upvotes: 2

Related Questions