Эта теме есть в главе 8 книги "A Tour of C++(Third edition)".
Concepts
Концепции нужны, что бы задать ограничения на аргументы шаблонов.
Рассмотрим sum()
#include<iostream>
#include<vector>
template < typename Seq, typename Value >
Value sum(Seq s, Value v)
{
for(const auto& x:s)
v += x;
return v;
}
int main()
{
std::vector v{1, 2, 3};
std::cout << sum(v, 0) << std::endl;
}
Аргумент шаблона Seq должен удовлетворять ряду требований, запишем их.
using std::ranges::range_value_t;
using std::ranges::iterator_t;
using std::iter_value_t;
using std::input_iterator;
using std::same_as;
template<typename S>
concept Sequence = requires(S a){
typename range_value_t<S>;
typename iterator_t<S>;
{a.begin()} -> same_as<iterator_t<S> >;
{a.end()} - > same_as < <iterator_t<S> >;
requires input_iterator< iterator_t<S> >;
requires same_as<range_value_t<S>, iter_value_t<S> >;
};
Эту концепцию мы можем использовать для записи функции
template<typename Seq, typename Num>
requires Sequence<Seq>
Num sum(Seq s, Num v)
{
for(const auto & x:s)
v += x;
return v;
}
Концепция - это предикат проверяемый в момент компиляции.
Для нашего случая удобно воспользоваться готовой концепцией.
#import<ragnes>
template<typename S>
concept Sequence = std::ranges::input_range<S>;
Зададим следующее ограничение
template<typename T, typename U = T>
concept Number =
requires(T x, U y){
x + y;
x - y;
x * y;
x / y;
x += y;
x -= y;
x *= y;
x /= y;
x = x;
x = 0;
};
Зададим следующую концепцию
template<typename T, typename U=T>
concept Arithmetic = Number<T,U> && Number<U, T>;
Окончательно запишем
using std::ranges::range_value_t;
template<Sequence Seq, Number Num>
requires Arithmetic < range_value_t<Seq>, Num >
Num sum(Seq s, Num v)
{
for(const auto& x:s)
v += x;
return v;
}