Concepts in C++20: An Evolution or a Revolution?


Let me conclude my series to concepts with this meta-post. Are concepts an evolution or a revolution in C++? The answer to this question bothered me quite a time.


I assume we all know what evolution or revolution means but let me be more precise. These definitions from re:invention are quite concise:

  • Evolution is defined as gradual change, adaptation, progression, metamorphosis.
  • Revolution is defined as forcible overthrow for an entirely new system…drastic, disruptive, far-reaching, momentous change.

To make it short. The crucial difference between evolution and revolution is if the change is gradual (evolution) or disruptive (revolution).

I had many discussions in the series to concepts. Consequentially, I was curious about what your opinion of concepts is. The answers I got are in German. For your convenience, I paraphrase it in English. Interestingly, my readers have a clear tendency to evolve. Honestly, I'm more on the revolution side.

Which argument speaks for evolution and which argument speaks for revolution?


evolution 4107273 1280

Image by Alexas_Fotos from Pixabay

Clear Abstraction 

When used properly, concepts should promote clean working with generic code at a higher level of abstraction.

In the longer term, the standard concepts should become increasingly idiomatic in C++. The interoperability and modular work, especially in larger teams, can be made more robust and less prone to errors, if more on abstract properties of the parameter classes is checked and less for purely syntactic "rollout" in generic code.

Simple Definition and meaningful Error Messages

You cannot do anything that you would not have been able to do with type-traits library, SFINAE and static_assert so far, even if it was very cumbersome and time-consuming. Their advantages lie in the simple definition and meaningful error messages.

Unconstrained Placeholders

Since C++11 we have auto to deduce the type of a variable from its initializer.

auto integ = add(2000, 11);

std::vector<int> myVec{1, 2, 3};
for (auto v: myVec) std::cout << v << std::endl;

auto is a kind of unconstrained placeholder. With C++20, we can use concepts as constrained placeholders.


template<typename T>                                   
concept Integral = std::is_integral<T>::value;

Integral auto integ = add(2000, 11);

std::vector<int> myVec{1, 2, 3};
for (Integral auto v: myVec) std::cout << v << std::endl;


To make it concise and evolutionary: you can use a constrained placeholder (concept) in each place you could use an unconstrained placeholder (auto).

Generic Lambdas

 With C++14 you can use a generic lambda (addLambda) which becomes essentially a function template (addTemplate).

// addLambdaGeneric.pp

#include <iostream>

auto addLambda = [](auto fir, auto sec){ return fir + sec; }; 

template <typename T, typename T2>                            
auto addTemplate(T fir, T2 sec){ return fir + sec; }

int main(){
    std::cout << addLambda(2000, 11.5);    // 2011.5
    std::cout << addTemplate(2000, 11.5);  // 2011.5


Using auto in a function declaration was not possible with C++14. Since C++20 you can use a constrained placeholder (concept) or an unconstrained placeholder (auto) in a function declaration and the function declaration becomes a function template with unconstrained (auto) or constrained (concept) parameters.

// addUnconstrainedConstrained.cpp

#include <concepts>
#include <iostream>

auto addUnconstrained(auto fir, auto sec){
     return fir + sec;

std::floating_point auto addConstrained(std::integral auto fir, 
                                        std::floating_point auto sec){
     return fir + sec;

int main(){
    std::cout << addUnconstrained(2000, 11.5); // 2011.5
    std::cout << addConstrained(2000, 11.5);   // 2011.5


I intentionally used a strange signature for my addConstrained function to make my point. 


france 63022 1280


Image by WikiImages from Pixabay

Template Requirements are verified

Admittedly, you can specify template requirements in C++11 in the template declaration.

// requirementsCheckSFINAE.cpp

#include <type_traits>

template<typename T,
         typename std::enable_if<std::is_integral<T>::value, T>:: type = 0>
T moduloOf(T t) {
    return t % 5;

int main() {

    auto res = moduloOf(5.5);



The function template moduloOf requires, that the T has to be integral. If T is not integral and, therefore, the expression std::is_integral<T>::value evaluates to false, the failed substitution is not an error. The compiler removes the overload from the set of all potential overloads. After that step, there is no valid overload left.


This technique is called SFINAE and stands for Substitution Failure Is Not An Error. 

Honestly, I only teach this technique in template classes. This does not hold for concepts. The issue becomes immediately obvious.

// requirementsCheckConcepts.cpp

#include <concepts>

std::integral auto moduloOf(std::integral auto t) {
    return t % 5;

int main() {

    auto res = moduloOf(5.5);





Definition of Templates radically improved

Thanks to the abbreviated function template syntax, the definition of a function template becomes a piece of cake. I already presented the new syntactic sugar in the function declarations of addConstrained, and moduloOf. Therefore, I skip the example.

Semantic Categories

Concepts do not stand for syntactic constraints but for semantic categories. 

Addable is a concept that stands for a syntactic constraint.


template<typename T>
concept Addable = has_plus<T>;    // bad; insufficient

template<Addable N> auto algo(const N& a, const N& b) // use two numbers
    // ...
    return a + b;

int x = 7;
int y = 9;
auto z = algo(x, y);   // z = 16

std::string xx = "7";
std::string yy = "9";
auto zz = algo(xx, yy);   // zz = "79"


I assume Addable behaves not like expected. The function template algo should accept arguments which model numbers and not just support the + operator. Consequentially, two strings can be used as arguments. This is bad because addition is commutative, but not string concatenation: "7" + "9" != "9" + "7".

The solution is quite simple. Define the concept Number. Number is a semantic category such as Equal, Callable, Predicate, or Monad are.

My Conclusion

Of course, many arguments speak for an evolutionary step or a revolutionary jump with concepts. Mainly because of the semantic categories I'm on the revolution side. Concepts such as Number, Equality, or Ordering remind me of Platon's word of ideas. It is revolutionary for me that we can now reason about programming in such categories. 

What's next?

The ranges library, that I present in the next post, is the first customer of concepts. Ranges support algorithms which can

  • operate directly on the container
  • be evaluated lazily
  • be composed



Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, Marko, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Animus24, Jozo Leko, John Breland, espkk, Louis St-Amour, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Neil Wang, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Tobi Heideman, Daniel Hufschläger, Red Trip, Alexander Schwarz, Tornike Porchxidze, Alessandro Pezzato, Evangelos Denaxas, Bob Perry, Satish Vangipuram, and Andi Ireland.


Thanks in particular to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, and Said Mert Turkal.



My special thanks to Embarcadero CBUIDER STUDIO FINAL ICONS 1024 Small



I'm happy to give online-seminars or face-to-face seminars world-wide. Please call me if you have any questions.

Bookable (Online)


Standard Seminars (English/German)

Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.


Contact Me

Modernes C++,






My Newest E-Books

Course: Modern C++ Concurrency in Practice

Course: C++ Standard Library including C++14 & C++17

Course: Embedded Programming with Modern C++

Course: Generic Programming (Templates)

Course: C++ Fundamentals for Professionals

Subscribe to the newsletter (+ pdf bundle)

Blog archive

Source Code


Today 1202

Yesterday 7645

Week 8847

Month 149054

All 6589135

Currently are 198 guests and no members online

Kubik-Rubik Joomla! Extensions

Latest comments