It is well known that throw
can be placed as the second or the third operand of C++ ternary operator ?:
. But can it be inside a comma subexpression of there operands? It looks like compilers diverge in this regard. Please consider an example:
#include <iostream>
void foo(bool b) {
int i = b ? 1 : (throw 0); //ok everywhere
if ( !b )
(std::cout << "smth\n", throw 0); //ok everywhere
i = b ? 2 : (std::cout << "smth\n", throw 0); //ok in MSVC only
};
This example is accepted by MSVC, but rejected by both GCC and Clang, demo: https://gcc.godbolt.org/z/6q46j5exP
Though the error message:
error: third operand to the conditional operator is of type 'void', but the second operand is neither a throw-expression nor of type 'void'
7 | i = b ? 2 : (std::cout << "smth\n", throw 0);
| ^
suggests that it was not rejected intentionally but rather the compiler thinks that the third operand not only has formal type void
but actually can return.
According to https://en.cppreference.com/w/cpp/language/operator_other, it seems that GCC/Clang are right since
Either E2 or E3 (but not both) is a (possibly parenthesized) throw-expression.
and here we have parenthesized comma expression just finishing with throw-expression.
According to the standard, is MSVC incorrect in accepting the last line of the example?