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
Tfor 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
Arithmeticusesstd::is_arithmetic_v<T>to check if the typeTsupports arithmetic operations. - The
addfunction template requires its parameter typeTto satisfy theArithmeticconcept. - In
main, integers satisfy theArithmeticconcept, 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
Containerchecks if a type hasbegin()andend()methods, which are common for standard containers. - The
printContainerfunction template is constrained to types satisfying theContainerconcept. std::vectorandstd::listsatisfy theContainerconcept, 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
conceptkeyword 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.
