I'm using std::variant to specify the types of properties that an entity in my project may have, and stumbled upon this code from cppreference:
std::visit([](auto&& arg)
{
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int>)
std::cout << "int with value " << arg << '\n';
else if constexpr (std::is_same_v<T, long>)
std::cout << "long with value " << arg << '\n';
else if constexpr (std::is_same_v<T, double>)
std::cout << "double with value " << arg << '\n';
else if constexpr (std::is_same_v<T, std::string>)
std::cout << "std::string with value " << std::quoted(arg) << '\n';
else
static_assert(always_false_v<T>, "non-exhaustive visitor!");
}, w);
always_false_v is defined as
template<class>
inline constexpr bool always_false_v = false;
I get that this checks at compile time if I'm handling all of the types in my variant which is pretty cool and helpful, but I'm puzzled as to why always_false_v<T> is required.
If I remove a branch from the ifs, intellisense in Visual Studio immediately sets red squigglies because the static_assert fails.
If I replace always_false_v<T> with false, intellisense doesn't complain but the static assert fails when I try to build.
Why is just false not enough? I would expect the else to never execute even at compile time, if it executes all the time, why is always_false_v<T> not equivalent to false (it looks like it's true which surely it cannot be)?