P0292R1 constexpr if has been included, on track for C++17. It seems useful (and can replace use of SFINAE), but a comment regarding static_assert being ill
Edit: I'm keeping this self-answer with examples and more detailed explanations of the misunderstandings that lead to this questions. The short answer by T.C. is strictly enough.
After rereading the proposal and on static_assert in the current draft, and I conclude that my worries were misguided. First of all, the emphasis here should be on template definition.
ill-formed; no diagnostic required for template definition
If a template is instantiated, any static_assert fire as expected. This presumably plays well with the statement I quoted:
... a discarded statement is not instantiated.
This is a bit vague to me, but I conclude that it means that templates occurring in the discarded statement will not be instantiated. Other code
however must be syntactically valid. A static_assert(F), [where F is false, either literally or a constexpr value] inside a discarded if constexpr clause will thus still 'bite' when the template containing the static_assert is instantiated. Or (not required, at the mercy of the compiler) already at declaration if it's known to always be false.
Examples: (live demo)
#include
template< typename T>
constexpr void some_library_foo(){
static_assert(std::is_same::value);
}
template< typename T>
constexpr void other_library_bar(){
static_assert(std::is_same::value);
}
template< typename T>
constexpr void buzz(){
// This template is ill-formed, (invalid) no diagnostic required,
// since there are no T which could make it valid. (As also mentioned
// in the answer by T.C.).
// That also means that neither of these are required to fire, but
// clang does (and very likely all compilers for similar cases), at
// least when buzz is instantiated.
static_assert(! std::is_same::value);
static_assert(false); // does fire already at declaration
// with latest version of clang
}
template
void g() {
if constexpr (IntCase){
some_library_foo();
// Both two static asserts will fire even though within if constexpr:
static_assert(!IntCase) ; // ill-formed diagnostic required if
// IntCase is true
static_assert(IntCase) ; // ill-formed diagnostic required if
// IntCase is false
// However, don't do this:
static_assert(false) ; // ill-formed, no diagnostic required,
// for the same reasons as with buzz().
} else {
other_library_bar();
}
}
int main(){
g();
g();
//g(); // ill-formed, diagnostic required
//g(); // ill-formed, diagnostic required
}
The standard text on static_assert is remarkably short. In standardese, it's a way to make the program ill-formed with diagnostic (as @immibis also pointed out):
7.6 ... If the value of the expression when so converted is true, the declaration has no effect. Otherwise, the program is ill-formed, and the resulting diagnostic message (1.4) shall include the text of the string-literal, if one is supplied ...