C++20coreadvanced
Constrained Templates (C++20 Addition)
C++20 · The Big Four · Compiler flag: -std=c++20
Explanation
Use concepts directly in template declarations for concise constraints.
Real-World Scenario
Define a generic container that requires comparable types for sorting.
Quick Snippet
snippet.cpp
template<std::totally_ordered T> class SortedContainer {};Full Example
constrained_templates.cpp
// CodeNebula - C++20 Example: Constrained Templates
// Compile: g++ -std=c++20 -Wall -Wextra -o example constrained_templates.cpp
// Demonstrates template<Concept T> syntax for constraining template
// parameters directly in the template parameter list.
#include <iostream>
#include <concepts>
#include <string>
#include <vector>
#include <numeric>
// ------------------------------------------------------------------
// 1. Concept definitions
// ------------------------------------------------------------------
template <typename T>
concept Arithmetic = std::integral<T> || std::floating_point<T>;
template <typename T>
concept Stringlike = std::convertible_to<T, std::string_view>;
template <typename T>
concept Container = requires(T c) {
typename T::value_type;
{ c.begin() };
{ c.end() };
{ c.size() } -> std::convertible_to<std::size_t>;
};
// ------------------------------------------------------------------
// 2. Constrained function templates: template<Concept T>
// ------------------------------------------------------------------
template <Arithmetic T>
T square(T x) {
return x * x;
}
template <Arithmetic T>
T average(const std::vector<T>& vals) {
T sum = std::accumulate(vals.begin(), vals.end(), T{});
return sum / static_cast<T>(vals.size());
}
template <Stringlike S>
std::string greet(S name) {
return "Hello, " + std::string(name) + "!";
}
// ------------------------------------------------------------------
// 3. Constrained class template
// ------------------------------------------------------------------
template <Arithmetic T>
class Stats {
std::vector<T> data_;
public:
void add(T val) { data_.push_back(val); }
T min_val() const {
T m = data_[0];
for (auto v : data_) if (v < m) m = v;
return m;
}
T max_val() const {
T m = data_[0];
for (auto v : data_) if (v > m) m = v;
return m;
}
T sum() const {
return std::accumulate(data_.begin(), data_.end(), T{});
}
void print() const {
std::cout << " Stats: min=" << min_val()
<< " max=" << max_val()
<< " sum=" << sum() << std::endl;
}
};
// ------------------------------------------------------------------
// 4. Constrained template with multiple parameters
// ------------------------------------------------------------------
template <Container C, Arithmetic T>
T sum_container_plus(const C& c, T extra) {
T total = extra;
for (const auto& elem : c) total += static_cast<T>(elem);
return total;
}
int main()
{
std::cout << "=== Constrained Function Templates ===" << std::endl;
std::cout << " square(5) = " << square(5) << std::endl;
std::cout << " square(2.5) = " << square(2.5) << std::endl;
// square(std::string("x")); // Compile error: not Arithmetic
std::vector<double> vals = {10.0, 20.0, 30.0, 40.0};
std::cout << " average({10,20,30,40}) = " << average(vals) << std::endl;
std::cout << "\n=== Stringlike Constraint ===" << std::endl;
std::cout << " " << greet("World") << std::endl;
std::string name = "C++20";
std::cout << " " << greet(name) << std::endl;
std::cout << "\n=== Constrained Class Template ===" << std::endl;
Stats<int> si;
si.add(3); si.add(7); si.add(1); si.add(9); si.add(4);
si.print();
Stats<double> sd;
sd.add(1.1); sd.add(2.2); sd.add(3.3);
sd.print();
std::cout << "\n=== Multiple Constrained Parameters ===" << std::endl;
std::vector<int> nums = {1, 2, 3, 4, 5};
std::cout << " sum + 100 = " << sum_container_plus(nums, 100) << std::endl;
std::cout << " sum + 0.5 = " << sum_container_plus(nums, 0.5) << std::endl;
return 0;
}
/*
Expected output:
=== Constrained Function Templates ===
square(5) = 25
square(2.5) = 6.25
average({10,20,30,40}) = 25
=== Stringlike Constraint ===
Hello, World!
Hello, C++20!
=== Constrained Class Template ===
Stats: min=1 max=9 sum=24
Stats: min=1.1 max=3.3 sum=6.6
=== Multiple Constrained Parameters ===
sum + 100 = 115
sum + 0.5 = 15.5
*/
Run command
g++ -std=c++20 -Wall -Wextra -o example constrained_templates.cpp