Defined in header
template<classInputIt,classOutputIt>OutputItadjacent_difference(InputItfirst,InputItlast,OutputItd_first); (1)(constexpr since C++20)template<classExecutionPolicy,classForwardIt1,classForwardIt2>ForwardIt2adjacent_difference(ExecutionPolicy&&policy,ForwardIt1first,ForwardIt1last,ForwardIt2d_first); (2) (since C++17)template<classInputIt,classOutputIt,classBinaryOp>OutputItadjacent_difference(InputItfirst,InputItlast,OutputItd_first,BinaryOpop); (3)(constexpr since C++20)template<classExecutionPolicy,classForwardIt1,classForwardIt2,classBinaryOp>ForwardIt2adjacent_difference(ExecutionPolicy&&policy,ForwardIt1first,ForwardIt1last,ForwardIt2d_first,BinaryOpop); (4) (since C++17)Let T be the value type of decltype(first).
1) If [first, last) is empty, does nothing.
Otherwise, performs the following operations in order:
Creates an accumulator acc of type T, and initializes it with *first.
Assigns acc to *d_first.
For each iterator iter in [++first, last) in order, performs the following operations in order:
a) Creates an object val of type T, and initializes it with *iter.
b) Computes val-acc(until C++20)val-std::move(acc)(since C++20).
c) Assigns the result to *++d_first.
d)Copy(until C++20)Move(since C++20) assigns from val to acc.
2) If [first, last) is empty, does nothing.
Otherwise, performs the following operations in order:
Assigns *first to *d_first.
For each integer i in [1, std::distance(first,last)), performs the following operations in order:
a) Computes curr-prev, where curr is the next ith iterator of first, and prev is the next i-1th iterator of first.
b) Assigns the result to *dest, where dest is the next ith iterator of d_first.
3) Same as (1), but computes op(val,acc)(until C++20)op(val,std::move(acc))(since C++20) instead.
4) Same as (2), but computes op(curr,prev) instead.
Given binary_op as the actual binary operation:
If any of the following conditions is satisfied, the program is ill-formed:
For overloads (1,3):
T is not constructible from *first.
acc is not
to d_first.
The result of binary_op(val,acc)(until C++20)binary_op(val,std::move(acc))(since C++20) is not writable to d_first.
For overloads (2,4):
*first is not writable to d_first.
The result of binary_op(*first,*first) is not writable to d_first.
Given d_last as the iterator to be
, if any of the following conditions is satisfied, the behavior is undefined:
For overloads (2,4), [first, last) and [d_first, d_last) overlaps.
binary_op modifies any element of [first, last) or [d_first, d_last).
binary_op invalidates any iterator or subrange in [first, last] or [d_first, d_last].
Parameters
first, last - the pair of iterators defining the
of elements to d_first - the beginning of the destination range policy - the
to use op - binary operation function object that will be applied. The signature of the function should be equivalent to the following:
Retfun(constType1&a,constType2&b);
The signature does not need to have const&.
The types Type1 and Type2 must be such that an object of type iterator_traits<InputIt>::value_type can be implicitly converted to both of them. The type Ret must be such that an object of type OutputIt can be dereferenced and assigned a value of type Ret.
Type requirements -InputIt must meet the requirements of
. -OutputIt must meet the requirements of
. -ForwardIt1, ForwardIt2 must meet the requirements of
. Return value
Iterator to the element past the last element written, or d_first if [first, last) is empty.
Complexity
Given N as std::distance(first,last):
1,2) Exactly N-1 applications of operator-.
3,4) Exactly N-1 applications of the binary function op.
Exceptions
The overloads with a template parameter named ExecutionPolicy report errors as follows:
If execution of a function invoked as part of the algorithm throws an exception and ExecutionPolicy is one of the
,
is called. For any other ExecutionPolicy, the behavior is implementation-defined.
If the algorithm fails to allocate memory,
is thrown.
Possible implementation
template<classInputIt,classOutputIt>constexpr// since C++20OutputItadjacent_difference(InputItfirst,InputItlast,OutputItd_first){if(first==last)returnd_first;typedeftypenamestd::iterator_traits<InputIt>::value_typevalue_t;value_tacc=*first;*d_first=acc;while(++first!=last){value_tval=*first;*++d_first=val-std::move(acc);// std::move since C++20acc=std::move(val);}return++d_first;}
template<classInputIt,classOutputIt,classBinaryOp>constexpr// since C++20OutputItadjacent_difference(InputItfirst,InputItlast,OutputItd_first,BinaryOpop){if(first==last)returnd_first;typedeftypenamestd::iterator_traits<InputIt>::value_typevalue_t;value_tacc=*first;*d_first=acc;while(++first!=last){value_tval=*first;*++d_first=op(val,std::move(acc));// std::move since C++20acc=std::move(val);}return++d_first;}Notes
acc was introduced because of the resolution of
. The reason of using acc rather than directly calculating the differences is because the semantic of the latter is confusing if the following types mismatch:
the value type of InputIt
the writable type(s) of OutputIt
the types of the parameters of operator- or op
the return type of operator- or op
acc serves as the intermediate object to cache values of the iterated elements:
its type is the value type of InputIt
the value written to d_first (which is the return value of operator- or op) is assigned to it
its value is passed to operator- or op
chari_array[4]={100,100,100,100};into_array[4];// OK: performs conversions when needed// 1. creates “acc” of type char (the value type)// 2. “acc” is assigned to the first element of “o_array”// 3. the char arguments are used for long multiplication (char -> long)// 4. the long product is assigned to the output range (long -> int)// 5. the next value of “i_array” is assigned to “acc”// 6. go back to step 3 to process the remaining elements in the input rangestd::adjacent_difference(i_array,i_array+4,o_array,std::multiplies<long>{});Example
Run this code
#include<array>#include<functional>#include<iostream>#include<iterator>#include<numeric>#include<vector>voidprintln(autocomment,constauto&sequence){std::cout<<comment;for(constauto&n:sequence)std::cout<<n<<' ';std::cout<<'\n';};intmain(){// Default implementation - the difference between two adjacent itemsstd::vectorv{4,6,9,13,18,19,19,15,10};println("Initially, v = ",v);std::adjacent_difference(v.begin(),v.end(),v.begin());println("Modified v = ",v);// Fibonaccistd::array<int,10>a{1};std::adjacent_difference(std::begin(a),std::prev(std::end(a)),std::next(std::begin(a)),std::plus<>{});println("Fibonacci, a = ",a);}Output:
Initially, v = 4 6 9 13 18 19 19 15 10 Modified v = 4 2 3 4 5 1 0 -4 -5 Fibonacci, a = 1 1 2 3 5 8 13 21 34 55 Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR Applied to Behavior as published Correct behavior
C++98 op could not have side effects it cannot modify
the ranges involved
C++98 the type requirements needed for the result
evaluations and assignments to be valid were missing added
C++17 for overloads (2,4), the result of each invocation
of operator- or op was assigned to a temporary
object, and that object is assigned to the output range assign the results
to the output
range directly See also