Throw and Ternary Operator in C++

Throw and ternary operator in C++

It is standard C++. Either (or both) of the then/else expressions in a conditional expression is allowed to be a throw-expression instead (C++98 5.16/2).

If Visual Studio crashes when compiling it... that would seem to be unfortunate!

Throwing with the ternary operator

A and B are different, incompatible types, so the expression true ? A() : B() is ill-typed (it'd have to be either an A or a B).

Move or throw using the ternary operator

This has to be a bug.

Either the move will be a move or the compilation should fail due to attempted copy of a unique_ptr (or a throw occurs in which case it doesn't matter).

q.get() == p.get() indeed shows that the internals have broken down, as this should not be possible.

I'd agree with cpplearner that this is bug 90393 (and all its dupes), which is reported as having been introduced in GCC 9.1.

Either downgrade, wait to upgrade, or reform your code into a nice if/else. /p>

Can an exception be thrown from the ternary operator?

The conditional operator is described in 5.16 [expr.cond]. Its paragraph 2 includes the following text:

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

That says that it is allowed to throw an exception from the conditional operator. However, even if the other branch is an lvalue, it is turned into an rvalue! Thus, it isn't possible to bind an lvalue to the result of a conditional expression. Aside from rewriting the condition using the comma operator, the code could be rewritten to only obtain the lvalue from the result of the conditional operator:

template <typename It>
typename std::iterator_traits<It>::reference
access(It it, It end) {
return *(it == end? throw std::runtime_error("no element"): it);
}

The somewhat tricky business is that returning a const reference from the function would compile but actually return a reference to a temporary!

Ternary operator: exception throwing and nesting

? : has lower precedence than &&, so yes, your first two examples are equivalent.

As for your third example, I'd write that as

int getIndex(int i) throw(Exception) {
return
i < 0 || i >= capacity ? throw IndexOutOfBoundsException() :
i >= length ? throw IndexOfEmptyFieldException() :
array[i]
;
}

I think "nested" conditional operators are fine as long as they're "serialized", i.e. they form what amounts to an if/elsif/else chain.

This particular case is debatable though, because only one branch actually returns a value. The other two just throw an exception, and that's usually nicer as a separate statement: Throwing an exception has no real value as an expression; it's used solely for its side effects.

Return throwing ternary operator?

Your example is valid and well-defined (assuming suitable definitions of Size and _data). As to "oftenly used" - I personally have never seen such a construct before, for what it's worth.

C++: Always-Throw function in conditional expression

You can use the comma operator like so:

int a = true ? 1 : (throw std::exception(), 0);
int b = true ? 1 : (foo(), 0);

See it working on godbolt.org.



Related Topics



Leave a reply



Submit