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;
}
I looked at definition of accumulate function in stl library. Here I found two macros __glibcxx_function_requires and __glibcxx_requires_valid_range, which are defined like this:
#define __glibcxx_function_requires(...)
# define __glibcxx_requires_valid_range(_First,_Last)
Please can you explain me, how they work and what they are doing ?
When _GLIBCXX_CONCEPT_CHECKS
is defined, so is this.
#define __glibcxx_function_requires(...) \
__gnu_cxx::__function_requires< __gnu_cxx::__VA_ARGS__ >();
So your posted code:
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
Resolves to this:
__gnu_cxx::__function_requires< _InputIteratorConcept<_InputIterator> >();
Which inlines to:
void (_InputIteratorConcept<_InputIterator>::*__x)() _IsUnused = &_InputIteratorConcept<_InputIterator>::__constraints;
This forces an instantiation of _InputIteratorConcept<_InputIterator>::__constraints
, which uses typedef
s to break compilation when _InputIterator
doesn't resemble an iterator.
__glibcxx_requires_valid_range
uses a similar technique to call one of several functions, depending on the iterator type. When appropriate (and fast enough), it will assert that __last
comes after __first
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With