In about 1987, I tried to design templates with proper interfaces. I failed. I wanted three properties for templates: full generality/expressiveness, zero overhead compared to hand coding, and good interfaces. I got Turing completeness, better than hand-coding performance, and lousy interfaces. The lack of well-specified interfaces led to the spectacularly bad error messages we saw over the years. The other two properties made templates a run-away success.

The solution to the interface specification problem was named “concepts” by Alex Stepanov. A concept is a set of requirements on a set of template arguments. “Concepts” is currently an ISO TS and it is proposed to be put into the standard proper for C++17. A concept is a compile-time predicate. For example, if a template takes a type argument, we can specify that an argument, T, can be an iterator, Iterator<T>, a random access iterator, Random_access_iterator<T>, or maybe a number, Number<T>. Similarly, we can specify that a set of template arguments must meet a predicate, for example Mergeable<In1, In2, Out>. This is very expressive and nicely cheap to compile (cheaper than using template metaprogramming workarounds). Students can use it after a lecture or two. You can, of course, define your own concepts and we can have libraries of concepts. Concepts enable overloading and eliminate the need for a lot of ad-hoc metaprogramming.

It was not easy to get to this point. In the early 2000s there were several ideas, including the one that became the current approach. However, we struggled with an approach based on specifying requirements as sets of functions. Dealing with implicit conversions was hard, interactions between existing unconstrained templates and templates with concepts were hard to manage, and writing a compiler that generated acceptable code took heroic efforts by Doug Gregor. Compilation speed was nowhere near acceptable, though. In the end, the committee pulled the plug on the C++0x concepts.

But we still wanted and needed concepts! Together with Gabriel Dos Reis and Andrew Sutton, I started to re-design concepts from scratch. In 2011, Alex Stepanov called a meeting in Palo Alto, where a largish group, including Sean Parent and Andrew Lumsdaine, attacked the problem from the user’s perspective: What would a properly constrained STL look like? Then, we went home to invent language mechanisms to approximate that ideal. That re-booted of the standards effort and led to the current TS and compiler. Andrew Sutton’s implementation has been used for over three years now and is part of GCC 6.0.

The current concept design focuses on the specification of interfaces. This has led some people to (wrongly) conjecture that we did not care about checking of template definitions and that concepts (as opposed to C++0x concepts) could not be used for that. In reality, the 2006 POPL paper shows how to do definition checking, Gabriel Dos Reis’ experimental language Liz implements those ideas, and recently Andrew Sutton quickly demonstrated that our predicate model easily handles definition checking even when implicit conversions and move operations are used. What we do worry about is how to gradually convert large C+98-style code bases to use definition checking and how to allow data collection, tracing, telemetry, etc. without interface changes.

We should have concepts in C++17, not just in a TS. “Concepts” as specified in the TS is an immensely useful feature for designers of generic code and together with constexpr functions lead to greatly simplified and more maintainable code. Sadly, the concepts-based Ranges library is by some deemed not ready for C++17, so it is likely to stay a TS for a while, – even though concepts were designed to exactly match the requirements of the STL algorithms.