std:: adjacent_difference
|
헤더 파일에 정의됨
<numeric>
|
||
|
template
<
class
InputIt,
class
OutputIt
>
OutputIt adjacent_difference
(
InputIt first, InputIt last,
|
(1) | (C++20부터 constexpr) |
|
template
<
class
ExecutionPolicy,
class
ForwardIt1,
class
ForwardIt2
>
|
(2) | (C++17부터) |
|
template
<
class
InputIt,
class
OutputIt,
class
BinaryOp
>
OutputIt adjacent_difference
(
InputIt first, InputIt last,
|
(3) | (C++20부터 constexpr) |
|
template
<
class
ExecutionPolicy,
class
ForwardIt1,
class
ForwardIt2,
class
BinaryOp
>
|
(4) | (C++17부터) |
T
를
decltype
(
first
)
의 값 타입이라고 하자.
[
first
,
last
)
가 비어 있으면, 아무 작업도 수행하지 않습니다.
-
T타입의 누산기 acc 를 생성하고 * first 로 초기화합니다. - acc 를 * d_first 에 할당합니다.
-
[++ first,last)범위 내의 각 반복자 iter 에 대해 순서대로 다음 작업을 수행합니다:
T
타입의 객체
val
을 생성하고
*
iter
로 초기화합니다.
[
first
,
last
)
가 비어 있으면, 아무 작업도 수행하지 않습니다.
- * first 를 * d_first 에 할당합니다.
-
각 정수
i
에 대해
[1,std:: distance ( first, last ))범위 내에서, 다음 작업들을 순서대로 수행합니다:
주어진 binary_op 를 실제 이항 연산으로 사용:
- 다음 조건 중 하나라도 만족되면 프로그램의 형식이 잘못되었습니다:
-
- 오버로드 (1,3) 의 경우:
-
-
T가 * first 로부터 생성 가능하지 않음. - acc 가 writable 하지 않음 d_first 에게.
- 다음 연산의 결과가 binary_op ( val, acc ) (C++20 이전) binary_op ( val, std :: move ( acc ) ) (C++20 이후) 가 d_first 에게 writable 하지 않음.
-
- 오버로드 (2,4) 의 경우:
-
- * first 가 d_first 에게 writable 하지 않음.
- 다음 연산의 결과가 binary_op ( * first, * first ) 가 d_first 에게 writable 하지 않음.
- 주어진 d_last 가 반환될 반복자일 때, 다음 조건 중 하나라도 만족되면 동작은 정의되지 않습니다:
|
(C++20부터) |
-
-
오버로드
(2,4)
의 경우,
[first,last)와[d_first,d_last)가 겹칩니다. -
binary_op
이
[first,last)또는[d_first,d_last)의 어떤 요소를 수정합니다. -
binary_op
이
[first,last]또는[d_first,d_last]의 어떤 반복자나 부분 범위를 무효화합니다.
-
오버로드
(2,4)
의 경우,
목차 |
매개변수
| first, last | - | 요소의 범위 를 정의하는 반복자 쌍 |
| d_first | - | 대상 범위의 시작 |
| policy | - | 사용할 실행 정책 |
| op | - |
적용될 이항 연산 함수 객체.
함수의 시그니처는 다음에 해당해야 합니다: Ret fun ( const Type1 & a, const Type2 & b ) ;
시그니처에
const
&
가 필요하지는 않습니다.
|
| 타입 요구사항 | ||
-
InputIt
는
LegacyInputIterator
요구사항을 충족해야 합니다.
|
||
-
OutputIt
는
LegacyOutputIterator
요구사항을 충족해야 합니다.
|
||
-
ForwardIt1, ForwardIt2
는
LegacyForwardIterator
요구사항을 충족해야 합니다.
|
||
반환값
마지막으로 기록된 요소의 다음 요소를 가리키는 반복자, 또는
d_first
(만약
[
first
,
last
)
범위가 비어 있는 경우).
복잡도
주어진 N 이 std:: distance ( first, last ) 인 경우:
예외
ExecutionPolicy
라는 템플릿 매개변수를 사용하는 오버로드는 다음과 같이 오류를 보고합니다:
-
알고리즘의 일부로 호출된 함수 실행 중 예외가 발생하고
ExecutionPolicy가 표준 정책 중 하나인 경우, std::terminate 가 호출됩니다. 다른ExecutionPolicy의 경우 동작은 구현에 따라 정의됩니다. - 알고리즘이 메모리 할당에 실패할 경우, std::bad_alloc 이 throw됩니다.
가능한 구현
| adjacent_difference (1) |
|---|
template<class InputIt, class OutputIt> constexpr // since C++20 OutputIt adjacent_difference(InputIt first, InputIt last, OutputIt d_first) { if (first == last) return d_first; typedef typename std::iterator_traits<InputIt>::value_type value_t; value_t acc = *first; *d_first = acc; while (++first != last) { value_t val = *first; *++d_first = val - std::move(acc); // std::move since C++20 acc = std::move(val); } return ++d_first; } |
| adjacent_difference (3) |
template<class InputIt, class OutputIt, class BinaryOp> constexpr // since C++20 OutputIt adjacent_difference(InputIt first, InputIt last, OutputIt d_first, BinaryOp op) { if (first == last) return d_first; typedef typename std::iterator_traits<InputIt>::value_type value_t; value_t acc = *first; *d_first = acc; while (++first != last) { value_t val = *first; *++d_first = op(val, std::move(acc)); // std::move since C++20 acc = std::move(val); } return ++d_first; } |
참고 사항
acc 는 LWG 이슈 539 의 해결로 도입되었습니다. 차이를 직접 계산하는 대신 acc 를 사용하는 이유는, 다음과 같은 타입 불일치가 발생할 경우 후자의 의미가 혼란스러울 수 있기 때문입니다:
-
InputIt의 값 타입 -
OutputIt의 쓰기 가능 타입(들) - operator - 또는 op 매개변수의 타입들
- operator - 또는 op 반환 타입
acc 는 반복되는 요소들의 값을 캐시하기 위한 중간 객체 역할을 합니다:
-
그 타입은
InputIt의 값 타입입니다 - d_first 에 기록된 값(이는 operator - 또는 op 의 반환값임)이 이에 할당됩니다
- 그 값이 operator - 또는 op 에 전달됩니다
char i_array[4] = {100, 100, 100, 100}; int o_array[4]; // OK: 필요한 경우 변환 수행 // 1. char 타입(값 타입)의 "acc" 생성 // 2. "acc"가 "o_array"의 첫 번째 요소에 할당됨 // 3. char 인수가 long 곱셈에 사용됨 (char → long) // 4. long 곱이 출력 범위에 할당됨 (long → int) // 5. "i_array"의 다음 값이 "acc"에 할당됨 // 6. 입력 범위의 나머지 요소들을 처리하기 위해 3단계로 돌아감 std::adjacent_difference(i_array, i_array + 4, o_array, std::multiplies<long>{});
예제
#include <array> #include <functional> #include <iostream> #include <iterator> #include <numeric> #include <vector> void println(auto comment, const auto& sequence) { std::cout << comment; for (const auto& n : sequence) std::cout << n << ' '; std::cout << '\n'; }; int main() { // 기본 구현 - 두 인접 항목 간의 차이 std::vector v{4, 6, 9, 13, 18, 19, 19, 15, 10}; println("초기값, v = ", v); std::adjacent_difference(v.begin(), v.end(), v.begin()); println("수정된 v = ", v); // 피보나치 std::array<int, 10> a {1}; std::adjacent_difference(std::begin(a), std::prev(std::end(a)), std::next(std::begin(a)), std::plus<>{}); println("피보나치, a = ", a); }
출력:
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
결함 보고서
다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| LWG 242 | C++98 | op 부작용(side effects)을 가질 수 없었음 | 관련 범위를 수정할 수 없음 |
| LWG 539 | C++98 |
결과 평가 및 할당이 유효하기 위해 필요한
타입 요구사항이 누락됨 |
추가됨 |
| LWG 3058 | C++17 |
오버로드
(2,4)
의 경우, 각
operator
-
또는
op
호출 결과가 임시 객체에
할당된 후 출력 범위에 할당됨 |
결과를 출력 범위에
직접 할당 |
참고 항목
|
요소 범위의 부분 합을 계산합니다
(function template) |
|
|
요소 범위를 합산하거나 접습니다
(function template) |