std::adjacent_difference - cppreference.com

Defined in header

<numeric>

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

writable

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

returned

, 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

range

of elements to d_first - the beginning of the destination range policy - the

execution policy

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

LegacyInputIterator

. -OutputIt must meet the requirements of

LegacyOutputIterator

. -ForwardIt1, ForwardIt2 must meet the requirements of

LegacyForwardIterator

. 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

standard policies

,

std::terminate

is called. For any other ExecutionPolicy, the behavior is implementation-defined.

If the algorithm fails to allocate memory,

std::bad_alloc

is thrown.

Possible implementation

adjacent_difference (1)

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;}

adjacent_difference (3)

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

LWG issue 539

. 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

LWG 242

C++98 op could not have side effects it cannot modify
the ranges involved

LWG 539

C++98 the type requirements needed for the result
evaluations and assignments to be valid were missing added

LWG 3058

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