Concepts (C++) Explained

Concepts are an extension to the templates feature provided by the C++ programming language. Concepts are named Boolean predicates on template parameters, evaluated at compile time. A concept may be associated with a template (class template, function template, member function of a class template, variable template, or alias template), in which case it serves as a constraint: it limits the set of arguments that are accepted as template parameters.

Originally dating back to suggestions for C++11, the original concepts specification has been revised multiple times before formally being standardised in C++20.

Main uses

The main uses of concepts are:

Constraint types and usage

There are five different places in a function template signature where a constraint can be used (labeled below from 1 through 5):[1]

template requires Concept2Concept3 auto myFunction(Concept4 auto param) requires Concept5;

The constraint forms Concept1 and Concept2 can be used in all kinds of templates.

Examples

Inheritance constraint

The following demonstrates using a concept as an upper bound for inheritance constraints on types, by creating a concept ExtendsPlayer satisfied only by classes which inherit from a base class Player, blocking any type that does not.

import std;

using std::is_base_of_v;using std::vector;

class Player ;

template concept ExtendsPlayer = is_base_of_v;

// T is required to be a type whose inheritance upper bound is Player,// blocking any type that does not inherit from Playertemplate void processListOfPlayers(const vector& players)

This is similar to constrained generics in Java, and is equivalent to the following example:import java.util.List;

class Player

public class Example

The following is a possible definition of the concept std::equality_comparable from the <concepts> header of the C++ Standard Library. This concept is satisfied by any type T such that for lvalues a and b of type T, the expressions a == b and a != b as well as the reverse b == a and b != a compile, and their results are convertible to a type that satisfies the concept "boolean-testable":

/** * @namespace std * @brief The C++ Standard Library namespace */namespace std

A function template constrained on this concept may be declared as follows:

// constrained abbreviated function template declaration // using a constrained placeholder type (Concept4 from above)void f(const equality_comparable auto& x);

or

// constrained function template declaration // using a type constraint (Concept1 from above)template void f(const T& x);

And may be called as usual:

// OK, int satisfies equality_comparablef(42);

Compiler diagnostics

If a programmer attempts to use a template argument that does not satisfy the requirements of the template, the compiler will generate an error. When concepts are not used, such errors are often difficult to understand because the error is not reported in the context of the call, but rather in an internal, often deeply nested, implementation context where the type was used.

For example, requires that its first two arguments be random-access iterators. If an argument is not an iterator, or is an iterator of a different category, an error will occur when attempts to use its parameters as bidirectional iterators. Consider std::list<T>, which implements a doubly-linked list, and is not random-access:

using std::list;

// std::list is typically a doubly-linked list, whose iterators are not random-accesslist l = ;std::sort(l.begin, l.end);

Typical compiler diagnostic without concepts is over 50 lines of output, beginning with a failure to compile an expression that attempts to subtract two iterators:

In instantiation of 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = std::_List_iterator<int>; _Compare = __gnu_cxx::__ops::_Iter_less_iter]':
 error: no match for 'operator-' (operand types are 'std::_List_iterator<int>' and 'std::_List_iterator<int>')
 std::__lg(__last - __first) * 2,

[..]

If concepts are used, the error can be detected and reported in the context of the call:

error: cannot call function 'void std::sort(_RAIter, _RAIter) [with _RAIter = std::_List_iterator<int>]'
note:   concept 'RandomAccessIterator' was not satisfied

Overload resolution

Concepts can be used to choose function template overloads and class template specializations based on properties of their template arguments, as an alternative to SFINAE and tag dispatching. If an argument satisfies more than one concept, the overload associated with the more constrained concept is chosen.

Type deduction

Concepts may be used instead of the unconstrained type deduction placeholder in variable declarations and function return types:

auto x1 = f(y); // the type of x1 is deduced to whatever f returnsSortable auto x2 = f(y); // the type of x2 is deduced, but only compiles if it satisfies Sortable

Implementation status

Concepts TS, as specified in ISO/IEC TS 19217:2015, are implemented as an experimental feature in GCC 6.[3] C++20 concepts are fully implemented in GCC 10,[4] MSVC 19.30,[5] and Clang 10.[6]

History

A different form of Concepts, popularly known as "C++0x Concepts"[7], was temporarily accepted into the working paper for C++11 but was removed in 2009.[8] In addition to concepts themselves, "C++0x Concepts" included concept maps (a feature that could make it possible, for example, for the concept Stack to accept, automatically mapping Stack operations such as to differently named operations on, such as) and axioms (a facility to specify semantic properties such as associativity or commutativity, allowing the compiler to take advantage of these properties without proof). The proposed syntax looked something like the following:template concept_map ForwardIterator ;

concept TotalOrder

The original proposal was ultimately abandoned due to resolution ambiguity in compilation as well as increased complexity in compile-time behavior, while axioms could not be verified during compilation. In contrast to this abandoned proposal, the C++20 version of Concepts is sometimes referred to as "Concepts Lite".[9]

During the C++ standards committee meeting in March 2016, the evolution working group moved to merge Concepts into the mainline C++17 standard, but the motion was defeated in full committee.[10]

Concepts v1 was merged into the C++20 draft.[11]

"The One Range" version of Range feature that depend on concepts was also merged into C++20.

Type constraints in other languages

In C#, a generic type constraint is expressed with a where clause, which can be as expressive as concepts but are not named.[12] using System;

public class MyGenericClass where T : IComparable, allows ref struct where U : class, notnull, new

Java has wildcard generics, which are not as expressive as concepts but can represent bounds on types.[13] import java.util.List;import java.util.stream.Collectors;

public static > List copyWhenGreater(List list, T threshold)

Kotlin, does not support Java-style type wildcards. However, it represents ? instead represented as * (for example, List<*>). It otherwise has C#-style where clauses:[14] fun copyWhenGreater(list: List, threshold: T): List where T : CharSequence, T : Comparable

Rust also uses where clauses to bound traits.use std::cmp::Ord;

struct MyStructwhere T: Ord + Default,

impl MyStructwhere T: Ord + Default,

See also

Notes

  1. Book: Fertig, Andreas . Andreas Fertig . 2021 . Programming with C++20 . Fertig Publications . 23 . 978-3-949323-01-0.
  2. Web site: ISO/IEC 14882:2020 . ISO . December 2020 . 14 July 2022 .
  3. Web site: GCC 6 Release Series - Changes, New Features, and Fixes.
  4. Web site: C++ compiler support (gcc).
  5. Web site: C++ compiler support.
  6. Web site: C++ Support in Clang.
  7. Web site: C++0x Concepts - Historical FAQs. ISO C++. ISO C++. isocpp.org. 27 February 2026.
  8. Web site: The C++0x "Remove Concepts" Decision . https://web.archive.org/web/20121009010252/https://www.drdobbs.com/cpp/the-c0x-remove-concepts-decision/218600111. 9 October 2012 . . . 2009-07-22.
  9. Web site: Concepts Lite: Constraining Templates with Predicates . 2013-02-24 . isocpp.org . Andrew Sutton.
  10. Web site: Why Concepts didn't make C++17. Honermann. Tom. 6 March 2016. honermann.net. 19 April 2016. 2 October 2018. https://web.archive.org/web/20181002123639/http://honermann.net/blog/2016/03/06/why-concepts-didnt-make-cxx17/. dead.
  11. Web site: 2017 Toronto ISO C++ Committee Discussion Thread (Concepts in C++20; Coroutines, Ranges and Networking TSes published) : cpp. 15 July 2017.
  12. Web site: where (generic type constraint). learn.microsoft.com. Microsoft Learn. 30 July 2024.
  13. Web site: Bounded Type Parameters. docs.oracle.com. Oracle Corporation. 15 October 2025.
  14. Web site: Generics: in, out, where Kotlin. kotlinlang.org. JetBrains s.r.o.. 15 October 2025.

References

External links