std::ranges::for_each, std::ranges::for_each_result
cppreference.net에서
| (C++23) <algorithm>
|
||
| 헤더 |
||
template< std::input_iterator I, std::sentinel_for<I> S,
class Proj = std::identity,
std::indirectly_unary_invocable<std::projected<I, Proj>> Fun >
constexpr for_each_result<I, Fun>
for_each( I first, S last, Fun f, Proj proj = {} );
|
에 정의됨 | 호출 시그니처 |
template< ranges::input_range R, class Proj = std::identity,
std::indirectly_unary_invocable
<std::projected<ranges::iterator_t<R>, Proj>> Fun >
constexpr for_each_result<ranges::borrowed_iterator_t<R>, Fun>
for_each( R&& r, Fun f, Proj proj = {} );
|
(1) | (C++20 이후) |
template< /*execution-policy*/ Ep, std::random_access_iterator I,
std::sized_sentinel_for<I> S, class Proj = std::identity,
std::indirectly_unary_invocable<std::projected<I, Proj>> Fun >
I for_each( Ep&& policy, I first, S last, Fun f, Proj proj = {} );
|
(2) | (C++20 이후) |
template< /*execution-policy*/ Ep,
/*sized-random-access-range*/ R, class Proj = std::identity,
std::indirectly_unary_invocable
<std::projected<ranges::iterator_t<R>, Proj>> Fun >
ranges::borrowed_iterator_t<R>
for_each( Ep&& policy, R&& r, Fun f, Proj proj = {} );
|
(3) | (C++26 이후) |
| (4) |
||
template< class I, class F >
using for_each_result = ranges::in_fun_result<I, F>;
|
(C++26 이후) | 헬퍼 타입 |
(5) /*execution-policy*/(C++20 이후)의 정의는 /*sized-random-access-range*/이 페이지를 참조하십시오;
의 정의는 f이 페이지proj를 참조하십시오.
[first, last)주어진 호출 가능 객체 r를 각 요소에 (f에 의해 투영된)
대상 범위
f 또는 에서 적용합니다.
f가 결과를 반환하면 그 결과는 무시됩니다.
policy1,2)는 대상 범위의 시작부터 순서대로 적용됩니다.3,4)는 순서대로 적용되지 않을 수 있습니다. 알고리즘은
for_each에 따라 실행됩니다.다른 병렬 알고리즘과 달리, 는 대상 범위의 요소를 임의로 복사하는 것이 허용되지 않습니다.이 페이지에 설명된 함수형 엔티티는
- 알고리즘 함수 객체
- (비공식적으로 niebloids라고 함)입니다. 즉:
- 명시적 템플릿 인자 목록은 이들 중 하나를 호출할 때 지정할 수 없습니다.이들 중 어느 것도 인자 종속 조회에 표시되지 않습니다.이들 중 하나가 함수 호출 연산자의 왼쪽에 이름으로
매개변수
| first, last | - | 대상 범위를 정의하는 반복자 쌍 |
| r | - | 대상 범위 |
| f | - | (프로젝션된) 요소들에 적용할 호출 가능 객체 |
| proj | - | 요소들에 적용할 프로젝션 |
| policy | - | 실행 정책 사용 |
반환값
1)
{last, std::move(f)}2)
{ranges::next(ranges::begin(r), ranges::end(r)), std::move(f)} R가 forward_range를 모델링하면, 그렇지 않으면 (C++26부터){ranges::end(r), std::move(f)}3)
last4)
ranges::next(ranges::begin(r), ranges::end(r)) R가 forward_range를 모델링하면, 그렇지 않으면 (C++26부터)ranges::end(r)복잡도
1,3) 정확히
ranges::distance(first, last)회 f 및 proj 적용.2,4) 정확히
ranges::distance(r)회 f 및 proj 적용.예외
3,4) 실행 과정 중:
- 병렬화에 필요한 임시 메모리 자원을 사용할 수 없는 경우, std::bad_alloc이 발생합니다.
- 알고리즘 인수를 통해 객체에 접근하는 동안 처리되지 않은 예외가 발생하면, 동작은 실행 정책에 따라 결정됩니다 (표준 정책, std::terminate가 호출됩니다).
참고
투영이 가변 참조를 반환하는 경우, f는 대상 범위의 요소를 수정할 수 있습니다.
오버로드 (1,2)의 경우, f는 상태를 가진 호출 가능 객체일 수 있습니다. 반환 값의 호출 가능 객체는 배치 작업의 최종 상태로 간주될 수 있습니다.
오버로드 (3,4)의 경우, 병렬 호출을 수행하기 위해 f의 여러 복사본이 생성될 수 있습니다. 반환 값에는 호출 가능 객체가 포함되지 않습니다. 병렬화는 종종 효율적인 상태 누적을 허용하지 않기 때문입니다.
가능한 구현
struct for_each_fn
{
template<std::input_iterator I, std::sentinel_for<I> S, class Proj = std::identity,
std::indirectly_unary_invocable<std::projected<I, Proj>> Fun>
constexpr ranges::for_each_result<I, Fun>
operator()(I first, S last, Fun f, Proj proj = {}) const
{
for (; first != last; ++first)
std::invoke(f, std::invoke(proj, *first));
return {std::move(first), std::move(f)};
}
template<ranges::input_range R, class Proj = std::identity,
std::indirectly_unary_invocable
<std::projected<ranges::iterator_t<R>, Proj>> Fun>
constexpr ranges::for_each_result<ranges::borrowed_iterator_t<R>, Fun>
operator()(R&& r, Fun f, Proj proj = {}) const
{
return (*this)(ranges::begin(r), ranges::end(r), std::move(f), std::ref(proj));
}
template<ranges::forward_range R, class Proj = std::identity,
std::indirectly_unary_invocable
<std::projected<ranges::iterator_t<R>, Proj>> Fun>
constexpr ranges::for_each_result<ranges::borrowed_iterator_t<R>, Fun>
operator()(R&& r, Fun f, Proj proj = {}) const
{
return (*this)(ranges::begin(r),
ranges::next(ranges::begin(r), ranges::end(r)),
std::move(f), std::ref(proj));
}
};
inline constexpr for_each_fn for_each;
|
예제
다음 예제는 람다 표현식을 사용하여 벡터의 모든 요소를 증가시킨 후, 호출 가능한 객체에서 오버로딩된 operator()을 사용하여 합계를 계산합니다. 합계를 계산할 때는 전용 알고리즘인 std::accumulate를 사용하는 것이 좋습니다.
이 코드 실행
#include <algorithm>
#include <cassert>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
struct Sum
{
void operator()(int n) { sum += n; }
int sum {0};
};
int main()
{
namespace ranges = std::ranges;
std::vector<int> nums {3, 4, 2, 8, 15, 267};
auto print = [](const auto& n) { std::cout << ' ' << n; };
std::cout << "before:";
ranges::for_each(std::as_const(nums), print);
print('\n');
ranges::for_each(nums, [](int& n) { ++n; });
// calls Sum::operator() for each number
auto [i, s] = ranges::for_each(nums.begin(), nums.end(), Sum());
assert(i == nums.end());
std::cout << "after: ";
ranges::for_each(nums.cbegin(), nums.cend(), print);
std::cout << "\n" "sum: " << s.sum << '\n';
using pair = std::pair<int, std::string>;
std::vector<pair> pairs {{1,"one"}, {2,"two"}, {3,"tree"}};
std::cout << "project the pair::first: ";
ranges::for_each(pairs, print, [](const pair& p) { return p.first; });
std::cout << "\n" "project the pair::second:";
ranges::for_each(pairs, print, &pair::second);
print('\n');
}
출력:
before: 3 4 2 8 15 267
after: 4 5 3 9 16 268
sum: 305
project the pair::first: 1 2 3
project the pair::second: one two tree
참고 항목
| 단항 함수 객체를 범위 로부터의 요소들에 적용합니다 (함수 템플릿) | |
(C++20) |
시퀀스의 처음 N개 요소에 함수 객체를 적용합니다 (알고리즘 함수 객체) |
(C++20) |
요소 범위에 함수를 적용합니다 (알고리즘 함수 객체) |
범위 기반 for for 루프(C++11)
|
범위에 대해 루프를 실행합니다 |