1

I am seeing some unexpected compile-time behavior when compiling a piece of code using MSVC 17.1.3 in C++20 standard compliance mode.

#include <type_traits>
#include <stdexcept>

template <typename T> void test()
{
    if constexpr(std::is_same<T,float>::value)
    {
        //Do something useful here and return
        return;
    }
    else
    {
        //Catch all invalid data types
        static_assert(false,"Template must be specialized to a float type");
        //Throw exception during runtime if the problem was not (for some unexplained reason) caught during compile time
        throw std::invalid_argument();
    }
}

int main(int argc, char * argv[])
{
    return 0;
}

This is a simplified version of a template function that is supposed to accept only certain data types during specialization and report an error in compile time when it was specialized with a wrong data type. For simplicity sake this example function only accepts float.

When compiled in C++17 mode, it works as expected - static_assert is never triggered when the function is never used or used with a float data type, and on contrary, when the function is specialized with anything but float, the static_assert is triggered.

However, when I switch MSVC settings to C++20 mode (/std:c++20 option), the static_assert is always triggered, even if I do not call the function at all. It seems like constexpr is not correctly calculated in compile time for some reason in C++20.

I am obviously missing something in terms of my knowledge of differences between C++17 and C++20. Any ideas?

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
Regus Pregus
  • 560
  • 3
  • 12
  • 3
    TL;DR: Your code is ill-formed, no diagnostic required (aka getting an error is not guaranteed), because every branch of `if constexpr` must be theoretically valid for some template argument. Probably MSVC was sloppy about this, and now they decided to start diagnosing this, like GCC and Clang do. For workarounds see https://stackoverflow.com/q/57787666/2752075 – HolyBlackCat Mar 31 '22 at 21:25
  • In your specific case it can just be `static_assert(std::is_same_v, "Template must be specialized to a float type");` instead of the whole `if constexpr` construct. The `throw` can never be compiled anyway if the static assertion fails. – user17732522 Mar 31 '22 at 21:29
  • Also see the comments in [Why is C++ static_assert different in Visual Studio 2022 17.1.0, and How to Replace It?](https://stackoverflow.com/questions/71346309/why-is-c-static-assert-different-in-visual-studio-2022-17-1-0-and-how-to-repl) on how this is a bug fix. – BoP Mar 31 '22 at 21:34

0 Answers0