template<typename _InputIterator, typename _Tp, typename _BinaryOperation>
inline _Tp
accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOperation __binary_op)
{
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
__glibcxx_requires_valid_range(__first, __last);
for (; __first != __last; ++__first)
__init = __binary_op(__init, *__first);
return __init;
}
Я посмотрел на определение функции накопления в библиотеке stl.
Здесь я нашел два макроса __glibcxx_function_requires и __glibcxx_requires_valid_range, которые определены следующим образом:
#define __glibcxx_function_requires(...)
# define __glibcxx_requires_valid_range(_First,_Last)
Не могли бы вы объяснить, как они работают и чем занимаются?
когда _GLIBCXX_CONCEPT_CHECKS
определяется, так и это.
#define __glibcxx_function_requires(...) \
__gnu_cxx::__function_requires< __gnu_cxx::__VA_ARGS__ >();
Итак, ваш опубликованный код:
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
Разрешается к этому:
__gnu_cxx::__function_requires< _InputIteratorConcept<_InputIterator> >();
Который указывает на:
void (_InputIteratorConcept<_InputIterator>::*__x)() _IsUnused = &_InputIteratorConcept<_InputIterator>::__constraints;
Это заставляет экземпляр _InputIteratorConcept<_InputIterator>::__constraints
, который использует typedef
S, чтобы сломать компиляцию, когда _InputIterator
не похож на итератор.
__glibcxx_requires_valid_range
использует аналогичную технику для вызова один из нескольких функции, в зависимости от типа итератора. Когда это уместно (и достаточно быстро), оно будет утверждать, что __last
идет после __first
Других решений пока нет …