What’s happening? Here is a simplified example:
template <typename T = void>
auto foo() -> T
static_assert(sizeof(T) < 1,
"I want to see this message")
While clang and gcc show the static_assert message and the information that int is not a struct and therefore certainly does not have a member cheesecake, MSVC just tells you the latter.
Compiled with /EHsc /nologo /W4 /c
main.cpp(9): error C2228: left of ‘.cheesecake’ must have class/struct/union
main.cpp(9): note: type is ‘void’
That’s it. No message about the failing static_assert.
This actually is a nice feature, which can help to reduce the compiler spew. The return type of function does not match the way it is used, so why bother looking into the details of the function?
But in real life, e.g. in older versions of sqlpp11, this can lead to trouble. For instance the following code
const auto count = db(update(tab)
.set(tab.name = "John Doe"));
sqlpp11 will reject this query at compile time, because the where condition is missing, which is likely to be an oversight (aka bug).
Clang and gcc users get an error message like this:
error: static_assert failed “calling where() or unconditionally() required”
However, MSVC just says:
error C3313: ‘count’: variable cannot have the type ‘void’
sqlpp11-0.42 and later remedies that by replacing void with better failure return types,e.g. assert_where_or_unconditionally_called_t. This ensures that errors can be comprehended, even if the static_assert is message is not presented by the compiler.
I will give more details about the techniques being used and how this can be utilized for testing in my talk at CppCon: “How to test static_assert?”