Эта теме есть в главе 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;
}