https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117272

--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Richard Kellnberger from comment #0)
> Since gcc 13 this is valid code:
> 
> ```C++
> template<typename T> void f(){
>     static_assert(false);
> }

Only because this function template is never instantiated.

> int main() {
> 
> }
> ```
> 
> This is as well:
> 
> ```C++
> #include <type_traits>
> 
> template<typename T> void f(){
>     if constexpr(std::is_same_v<T, int>) {
> 
>     } else {
>         static_assert(false);
>     }
> }
> 
> int main() {
>     f<int>();
> }
> ```
> 
> The `static_assert(false)` is ignored if it is not reached due to
> templating.

It's not that it's not "reached", because this isn't about control flow. It's
about whether it's in a discarded statement or not. A discarded statement in a
function template is not instantiated at all. The static_assert is not even
part of the function when the type is int.

> If I placed it into the `if` block instead the code would be
> ill-formed.

Yes, because when the type is int the static_assert(false) would be
instantiated.

> By the same logic the following should be valid, but it is not.

No, because it's literally not "the same logic".

In your last example the static_assert(false) is not in a discarded statement
so is always instantiated by every specialization of the function. It's just
like your first example which is ill-formed if ever called. Returning "before"
the static_assert doesn't make any difference. A static_assert is checked when
the function is instantiated at compile time, not when it's executed at
runtime.

Reply via email to