Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
472 views
in Technique[技术] by (71.8m points)

c++ - Can an exception be thrown from the ternary operator?

Sometimes it is convenient or even necessary to have a function which just one statement (it is necessary when returning a constexpr). If a condition needs to be checked and only one statement is allowed, the conditional operator is the only option. In case of an error it would be nice to throw an exception from the conditional operator, e.g.:

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 above function doesn't compile, however, when used for example as (live example):

std::vector<int> v;
access(v.begin(), v.end());

The compiler complains about trying to bind a non-const reference to a temporary. The compiler doesn't complain about the throw-expression per se, though. So the question: Can exceptions be thrown from the conditional operator and, if so, what's going wrong with the above code?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...