Category Archives: TMP

sqlpp11-0.42 released: Improved compile-time error messages for MSVC

Since end of 2015, sqlpp11 can be compiled with MSVC. When people started using it, it turned out that some of the carefully crafted static_assert messages were not shown by MSVC.

What’s happening? Here is a simplified example:

 

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
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

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?”

 

(Almost) Generic Comparison Operator For Structs

Introduction

A simple struct is easy to write. The compiler generates default constructors for us (unless we disturb it). It is readily to be used in vectors and lists, the world is nice.

And then you want to use you shiny new struct as a key in a map. Hmmpf. Need to write a less operator…

OK, so lets assume this is our struct:

Here’s a handcrafted less operator:

This is annoying to write. It is prone to errors while writing it the first time and also when time comes for maintenance (e.g lets add a language and swap title and author).

Macros come to mind, but many people frown on them.

Pointer-to-data-member to the rescue

Pointers to data members look quite weird if you aren’t used to them. But they allow us to specify access to data members of a struct via the pointer-to-member-access operators.

In combination with variadic templates we can write a generic less function that compares structs by data members with a given precedence.

m and rest sure look a bit crazy, being mixed with T, but they get the job done. They are used to iterate through a given order of data members.

And this is how we can use it to compare Talk objects:

This is nice and simple again, suiting a simple struct 🙂