C++ concept
Keyword
The concept
keyword in C++ was introduced in C++20 to define constraints on template parameters. A concept specifies requirements for template arguments, such as supported operations, type traits, or valid expressions. It makes generic programming more robust by ensuring that only valid types can be used with a template, providing clearer error messages during compilation.
Concepts improve readability, enforce type safety, and reduce template instantiation errors. They are essential for modern C++ programming and simplify working with templates by explicitly declaring the requirements for template parameters.
Syntax
template <typename T>
concept ConceptName = constraint_expression;
- template<typename T>
- Defines a template parameter
T
for the concept. - ConceptName
- The name of the concept being defined.
- constraint_expression
- An expression that specifies the requirements for the concept. It can include type traits, valid operations, or expressions.
Examples
Example 1: Basic Concept for Arithmetic Types
This example defines a concept that ensures a type supports arithmetic operations like addition and subtraction.
#include <iostream>
#include <concepts>
// Define a concept for arithmetic types
template <typename T>
concept Arithmetic = std::is_arithmetic_v<T>;
// Function template using the concept
template <Arithmetic T>
T add(T a, T b) {
return a + b;
}
int main() {
std::cout << "Sum: " << add(10, 20) << std::endl; // Valid
// Uncommenting the following line will cause a compile-time error
// std::cout << add(std::string("Hello"), std::string("World")) << std::endl;
return 0;
}
Output:
Sum: 30
Explanation:
- The concept
Arithmetic
usesstd::is_arithmetic_v<T>
to check if the typeT
supports arithmetic operations. - The
add
function template requires its parameter typeT
to satisfy theArithmetic
concept. - In
main
, integers satisfy theArithmetic
concept, so the addition operation is valid. - Attempting to use non-arithmetic types (e.g.,
std::string
) results in a clear compile-time error.
Example 2: Concept for Containers
This example defines a concept to constrain types to standard containers that provide begin()
and end()
methods.
#include <iostream>
#include <vector>
#include <list>
#include <concepts>
// Define a concept for containers
template <typename T>
concept Container = requires(T c) {
c.begin(); // Must have a begin() method
c.end(); // Must have an end() method
};
// Function template using the concept
template <Container T>
void printContainer(const T& container) {
for (const auto& element : container) {
std::cout << element << " ";
}
std::cout << std::endl;
}
int main() {
std::vector<int> vec = {1, 2, 3};
std::list<int> lst = {4, 5, 6};
printContainer(vec); // Valid
printContainer(lst); // Valid
// Uncommenting the following line will cause a compile-time error
// printContainer(5); // Not a container
return 0;
}
Output:
1 2 3
4 5 6
Explanation:
- The concept
Container
checks if a type hasbegin()
andend()
methods, which are common for standard containers. - The
printContainer
function template is constrained to types satisfying theContainer
concept. std::vector
andstd::list
satisfy theContainer
concept, so their elements are printed.- Passing a non-container type results in a compile-time error with a clear diagnostic message.
Key Points about concept Keyword
- The
concept
keyword is used to define compile-time constraints for template parameters. - Concepts simplify template programming by providing clear, concise requirements for template arguments.
- They improve error diagnostics and help prevent template instantiation errors.
- Concepts can validate types, operations, and expressions during compilation.
- Using concepts requires a C++20-compatible compiler and enabling the C++20 standard.