Mopping up template barf with static_assert

Templates are a mixed blessing for C++ developers. On the one hand, templates avoid code duplication as most impressively demonstrated by the standard template library. The template mechanism, in contrast to preprocessor macros, is aware of the C++ language and part of it. Compilers can produce helpful error messages – and some compilers even do so.

Some compilers, however, fail in providing clear template compilation error messages. If you make a mistake, you are greeted by a bucket load of irritating notes on what went wrong in detail. Since it is down to you to identify the relevant chunks, this is often referred to as template barf.

A simple template function

Consider the following template function which calculates the hypothenuse given the two other sides of a right-angled triangle:

From the declaration of the function it should be clear that it is designed to work with floating point numbers (using the common  T instead of  Floating_Point would destroy the interface’s clarity).

The compiler, our cryptic friend

Let us forget a moment that we are infallible programmers and consider we use our function in a slightly less-than-correct way:

What will happen if we compile this? Compilation will fail. Exactly how it will fail depends on your compiler. This is the output of Visual Studio 2012:

This is actually one of the better error messages we encountered. You must be above 18 to see the ones generated by other compilers for the same code. Even though we made a simple, not-so-honest mistake, the compiler merely reports on symptoms ( * operator not found,  sqrt not defined for std::string). The root of the problem is left for the user to find.

Custom error messages with static_assert

The new C++11 standard introduced the  static_assert keyword which helps deal with template barf. The syntax is like this:

static_assert checks a boolean at compile time, which is also the main difference to the assert macro provided by the C part of C++. If the boolean is true, compilation continues without further ado; run time performance is not affected. If the boolean is false, however, the compiler will mark the compilation as failed and print the error message you provided. Depending on your compiler, compilation might continue for a while, though. Thus,  static_assert does not remove template barf completely. Think of it more like an introductory “I had a Cheeseburger with bacon for lunch” before handing you the mop.

Type checking with is_floating_point

To be actually helpful, you need sources for booleans which are fixed at compile time, but yield values which depend on other circumstances fixed at compile time. Normal functions won’t do, because a function is evaluated when it is called at run time. What we need are template metafunctions. Template metafunctions are templated types, usually structs, designed to provide a  static constant member  value and the  typedef type. Depending on the provided template argument,  type and  value will be set accordingly.

Template metafunctions will prominently feature in other articles. For now, we will look at template metafunctions provided by the C++11′s very own standard template library:

std::is_floating_point<>  is a metafunction which determines whether the passed type is a floating point type or not. It defines the  value member as  true for types such as  float and double, and  false for non-floating point types such as  int or std::string. In our wrong usage scenario, the error message changes to this:

The error message we got earlier is still there and still valid. However, the message we put in the  static_assert is printed. Our custom message clearly transports the root cause of the compilation error: We should have used a floating point type to call hypothenuse, but we used std::string instead.

Conclusion

static_assert is not the best imaginable way to deal with concepts a type must satisfy in order to be used in the template. More sophisticated language features are on the way and might be included in the next C++ standard or technical report. Until then,  static_assert provides a somewhat cumbersome, yet powerful way to make our template functions and classes easier to use correctly.

2 thoughts on “Mopping up template barf with static_assert

  1. Nice blog! *bookmark*

    The compiler messages are hard to read because they exceed the number of printed letters in the box in one line and one has to scroll a lot. Furthermore the first line is hard to read, because of the mouseover.

    There is a typo in the italic typeset of the word “how”.

    Can you additionally provide a list of useful STL template metafunctions or link a reference?

Leave a Reply

Your email address will not be published. Required fields are marked *

*


six + 6 =

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">