범위 어댑터
범위 어댑터는 범위에서 뷰(네임스페이스의 std::views
View 클래스 중 하나)를 만듭니다. 보기 형식을 직접 만드는 대신 어댑터를 사용하여 보기를 만드는 것이 좋습니다. 어댑터는 보기에 액세스하기 위한 방법입니다. 보기 형식의 인스턴스를 직접 만드는 것보다 사용하기 쉽고 경우에 따라 더 효율적입니다.
보기는 범위의 요소를 참조하는 경량 개체입니다. 보기는 다음을 수행할 수 있습니다.
- 범위의 특정 요소로만 구성됩니다.
- 범위에서 요소의 변환을 나타냅니다.
- 범위의 반대 또는 첫 번째
n
요소만이어야 합니다. - 이전 항목의 조합이어야 합니다.
보기는 얼마나 많은 요소가 관련되어 있든 관계없이 복사, 할당 및 파괴하는 저렴한 O(1)
값입니다. 다음 예시를 참조하세요.
// requires /std:c++20 or later
#include <ranges>
#include <vector>
#include <iostream>
int main()
{
std::vector<int> input = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto divisible_by_three = [](const int n) {return n % 3 == 0;};
auto square = [](const int n) {return n * n;};
auto x = input | std::views::filter(divisible_by_three)
| std::views::transform(square);
for (int i : x)
{
std::cout << i << ' ';
}
}
0 9 36 81
첫 번째 범위 어댑터인 이 어댑터 filter
에서는 3으로 나눌 수 있는 요소가 input
포함된 뷰를 제공합니다. 다른 범위 어댑터 transform
, 3으로 나눌 수 있는 요소를 포함 하는 보기를 사용 하 고 해당 요소의 사각형의 보기를 제공 합니다.
범위 어댑터에서 뷰를 생성하는 경우 해당 뷰를 생성하기 위해 범위의 모든 요소를 변환하는 비용이 발생하지 않습니다. 보기에서 요소를 처리하는 비용은 해당 요소에 액세스할 때만 지불됩니다.
뷰를 만드는 것은 나중에 작업을 수행할 준비를 하는 것입니다. 이전 예제에서 뷰를 만들면 3으로 나눌 수 있는 모든 요소를 찾거나 해당 요소를 제곱하지는 않습니다. 작업은 보기의 요소에 액세스할 때만 발생합니다.
뷰의 요소는 일반적으로 뷰를 만드는 데 사용되는 범위의 실제 요소입니다. 보기는 일반적으로 요소를 소유하지 않습니다. 은 (을) 제외하고 owning_view
단지 그들을 가리킵니다. 요소를 변경하면 뷰가 만들어진 범위의 해당 요소가 변경됩니다. 다음 예제에서는 이 동작을 보여줍니다.
#include <algorithm>
#include <iostream>
#include <ranges>
int main()
{
int input[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto even = [](const int n) { return n % 2 == 0; };
auto x = input | std::views::filter(even); // create a view of the even elements from input
for (int &i : x)
{
std::cout << i << ' '; // 0 2 4 6 8 10
}
std::cout << '\n';
std::ranges::fill(x, 42); // changes the evens from input[] to 42
for (int &i : input) // demonstrates that the even elements in the range are modified
{
std::cout << i << ' '; // // 42 1 42 3 42 5 42 7 42 9 42
}
}
범위 어댑터는 다양한 형태로 제공됩니다. 예를 들어 다음을 통해 보기를 생성할 수 있는 범위 어댑터가 있습니다.
범위 어댑터는 함께 연결(구성)할 수 있습니다. 이것이 바로 범위의 힘과 유연성이 가장 명백한 곳입니다. 범위 어댑터를 작성하면 이전 STL(표준 템플릿 라이브러리) 알고리즘의 핵심 문제를 해결할 수 있습니다. 즉, 함께 연결하기가 쉽지 않습니다.
다음 범위 어댑터는 네임스페이 std::views
스에서 사용할 수 있습니다. std::views
네임스페이스는 편의 별칭입니다std::ranges::views
.
범위 어댑터 | 설명 |
---|---|
all C++20 |
범위와 해당 요소를 참조하는 뷰를 만듭니다. |
common C++20 |
그렇지 않은 범위에서 동일한 반복기 및 sentinel 형식이 있는 뷰를 만듭니다. |
counted C++20 |
지정된 위치에서 시작하여 범위의 첫 번째 n 개 요소 보기를 만듭니다. |
drop C++20 |
다른 보기에서 보기를 만들고 앞에서 지정된 수의 요소를 건너뜁니다. |
drop_while C++20 |
지정된 조건과 일치하는 선행 요소가 삭제된 후에 남아 있는 범위의 요소가 포함된 뷰를 만듭니다. |
elements C++20 |
선택한 인덱스의 뷰를 범위의 각 튜플과 유사한 값으로 만듭니다. |
empty C++20 |
요소가 없는 뷰를 만듭니다. |
filter C++20 |
지정된 조건과 일치하는 범위의 요소가 포함된 뷰를 만듭니다. |
iota C++20 |
증가하는 값의 시퀀스가 포함된 뷰를 만듭니다. |
istream C++20 |
스트림의 요소에 대한 뷰를 만듭니다. |
join C++20 |
여러 범위의 모든 요소를 단일 보기로 결합하는 뷰를 만듭니다. |
keys C++20 |
컬렉션의 각 튜플과 유사한 값에 첫 번째 인덱스의 뷰를 만듭니다. |
lazy_split C++20 |
구분 기호에 따라 보기를 하위 범위로 분할합니다. |
reverse C++20 |
범위 요소의 뷰를 역순으로 만듭니다. |
single C++20 |
하나의 요소가 포함된 뷰를 만듭니다. |
split C++20 |
구분 기호에 따라 보기를 하위 범위로 분할합니다. |
take C++20 |
다른 보기에서 첫 번째 n 요소의 뷰를 만듭니다. |
take_while C++20 |
지정된 조건과 일치하는 범위의 선행 요소가 포함된 뷰를 만듭니다. |
transform C++20 |
다른 보기에서 변환된 요소의 뷰를 만듭니다. |
values C++20 |
컬렉션의 각 튜플과 유사한 값에 두 번째 인덱스의 뷰를 만듭니다. |
이전 표에서 범위 어댑터에서는 일반적으로 범위를 가져와 뷰를 생성하는 것으로 설명됩니다. 정확하게 말하자면 범위 어댑터에는 다음 중 하나를 허용하는 범위 인수가 있습니다.
cv-unqualified
형식 모델view
및 인수는 rvalue이거나 복사할 수 있습니다.- 인수를 lvalue로 전달하면 뷰만큼 모델링
range
하고 라이브 상태여야 합니다. - 인수를 호출
owning_view
할 때와 같이 rvalue로 전달하면 모델링range
해야movable
합니다.
범위 어댑터 함수는 일반적으로 함수 호출처럼 보이고 전달할 수 있는 형식에 제약 조건을 적용하는 함수 개체입니다.
범위 어댑터와 파이프 작업(|
)의 결과를 함수 개체가 예상되는 코드에 전달할 수 있습니다. 다음 예제에서는 범위 어댑터에서 split
함수 개체이므로 범위 어댑터에서 만드는 뷰가 함수 호출 transform
에 의해 범위 어댑터에 전달 transform
됩니다.
std::map<int, string> x = {{0, "Hello, world"}, {42, "Goodbye, world"}};
auto y = x | views::values | views::transform(views::split(' '));
// y is a range whose elements are ranges of whitespace-delimited strings from each value in x:
// {{"Hello", "world"}, {"Goodbye", "world"}}
all
범위에 있는 모든 요소의 보기를 만듭니다.
template <ranges::viewable_range R>
constexpr ranges::view auto all(R&& rg) const noexcept;
매개 변수
R
기본 범위의 형식입니다.
rg
뷰를 만들 범위입니다.
반환 값
- 이미 뷰인 경우
rg
.의rg
복사본입니다. - 뷰가 아닌 lvalue
ref_view
이면rg
을 참조하는rg
값입니다. 보기의 수명은 .의rg
수명에 연결됩니다. - 임시 개체와 같은 비보기 rvalue이거나 범위를
std::move
전달한 결과인 경우rg
.owning_view
반환된 뷰의 형식을 가져오는 데 사용합니다 std::views::all_t<decltype((rg))>
.
설명
이 범위 어댑터를 사용하여 범위를 보기로 변환하는 가장 좋은 방법입니다. 범위에서 뷰를 만드는 한 가지 이유는 값으로 범위를 전달하는 데 비용이 많이 들 수 있는 경우 값으로 전달하는 것입니다.
보기가 생성, 복사 및 삭제하는 데 저렴하기 때문에 범위에 대한 보기를 가져오는 것은 값으로 헤비급 범위를 전달하는 데 유용한 대안입니다. 가능한 예외는 owning_view
기본 범위를 소유하는 뷰인 것입니다.
일반적으로 뷰를 삭제하는 최악의 시나리오는 O(N)
범위의 요소 수에 복잡성이 있습니다. 요소로 N
보기 복사본을 삭제 K
하더라도 기본 범위가 한 번만 제거되기 때문에 전체 복잡성이 여전히 O(N)
복잡합니다.
예: all
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v = {1,2,3,4,5,6,7,8,9,10};
auto myRefView = std::views::all(v); // create a ref_view of the vector
std::cout << myRefView.size() << '\n'; // 10
auto myOwningView = std::views::all(std::move(v)); // create an owning_view from a moved vector
std::cout << myRefView.size() << '\n'; // outputs 0 because myOwningView now owns the elements
std::cout << v.size() << '\n'; // outputs 0 because myOwningView now owns the elements
std::cout << myOwningView.size(); // 10
}
10
0
0
10
common
그렇지 않을 수 있는 범위에서 동일한 시작 반복기 및 sentinel 형식의 뷰를 만듭니다.
template <ranges::viewable_range R>
constexpr ranges::view auto common(R&& rg) const noexcept;
매개 변수
R
기본 범위의 형식입니다.
rg
뷰를 만들 범위입니다.
반환 값
views::all(rg)
반복기 및 sentinel 형식이 같은 범위이면rg /a0>입니다. common_view(views::all(rg))
반복기 및 sentinel 형식이 서로 다른 경우rg
설명
API에서 시작 반복기와 엔드 센티넬이 동일한 형식을 갖도록 요구하고 사용 중인 뷰가 해당 요구 사항을 충족하지 않는 경우(또는 해당 항목인지 모르는 경우) 이 범위 어댑터를 사용하여 만듭니 common_view
다. 시작 반복기의 형식과 끝 센티넬의 형식이 동일해야 합니다.
예: common
// requires /std:c++20 or higher
#include <ranges>
#include <iostream>
#include <numeric>
#include <list>
int main()
{
std::list<int> lst{1, 2, 3, 4, 5, 6, 7, 8, 9};
auto firstFive = std::views::take(lst, 5);
// firstFive.begin(), firstFive.end() have different types: counted_iterator versus default_sentinel
// auto r = std::accumulate(firstFive.begin(), firstFive.end(), 0); // Error: accumulate() requires firstFive.begin() and firstFive.end() types to be the same.
auto common = std::views::common(firstFive); // create a common_view that has the same begin/end iterator types
std::cout << std::accumulate(common.begin(), common.end(), 0); // Now you can call the API because the iterator types are the same. Outputs 15 (1+2+3+4+5)
}
15
counted
지정된 위치에서 시작하여 범위의 첫 번째 count
요소 보기를 만듭니다.
template<class Iterator>
constexpr auto counted(Iterator&& it, iter_difference_t<Iterator> count);
매개 변수
DifferenceType
개수의 형식입니다.
Iterator
반복기의 형식입니다.
count
뷰에 포함할 요소의 수입니다. 음수가 아니어야 합니다.
- 이면
count == 0
빈span
항목이 반환됩니다. - 범위의 요소 수보다 크면
count
동작이 정의되지 않습니다.
it
시작할 범위의 요소에 대한 반복기입니다. 반복기가 가리키는 요소는 만든 뷰에 포함됩니다.
반환 값
A span
는 해당 요소를 연속적으로 저장하는 배열, 벡터 및 기타 컨테이너에 대한 경우 it
contiguous_iterator
반환됩니다. 그렇지 않으면 a가 subrange
반환됩니다.
설명
포함된 요소는 다음과 같습니다 [it, count)
.
뷰를 만든 후에는 변경 내용으로 만든 범위가 있더라도 보기의 요소 수는 동일하게 유지됩니다. 그러나 기본 범위가 변경되면 보기에서 요소에 액세스하면 정의되지 않은 동작이 발생할 수 있습니다.
예: counted
// requires /std:c++20 or later
#include <algorithm>
#include <ranges>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto pos5 = std::ranges::find(v, 5);
auto countedView = std::views::counted(pos5, 5);
for (auto e : countedView) // outputs 5 6 7 8 9
{
std::cout << e << ' ';
}
std::cout << '\n';
// You can pass the range directly if it supports input_or_output_iterator, in which case
// the count starts from the first element
const char chars[] = { 'H','i',' ','t','h','e','r','e' };
for (char c : std::views::counted(chars, 2))
{
std::cout << c; // outputs Hi
}
}
5 6 7 8 9
Hi
drop
범위의 첫 번째 n 요소를 제외하는 뷰를 만듭니다.
1) template<ranges::viewable_range R>
constexpr ranges::view auto drop(R&& rg, ranges::range_difference_t<R> count);
2) template<class DifferenceType>
constexpr /* range closure object */ drop(DifferenceType&& count);
매개 변수
DifferenceType
건너뛸 요소 수를 설명하는 형식입니다.
count
앞에서 삭제할 요소의 수입니다 rg
. 음수가 아니어야 합니다.
- 이면
count == 0
모든 요소가rg
반환됩니다. - 요소
rg
수보다 크면count
빈 보기가 반환됩니다.
R
범위의 형식입니다.
rg
보기를 만드는 데 사용되는 범위입니다.
반환 값
지정된 개수의 요소가 전면에서 삭제된 기본 범위의 뷰입니다.
기본 범위에 empty_view
있는 것보다 삭제할 요소를 더 많이 지정하면 반환됩니다.
반환된 뷰는 일반적으로는 아니지만 항상 특수화되는 drop_view
것은 아닙니다. 구체적인 요건은 다음과 같습니다.
- 의 특수화이거나 , ,
subrange
basic_string_view
iota_view
또는 둘 다sized_range
random_access_range
의 특수화empty_view
span
인 경우V
결과는 특수화입니다.V
- 그렇지 않으면 결과는 .입니다
drop_view
.
설명
뷰를 만든 후에는 뷰가 변경된 보기에서 생성된 경우에도 보기의 요소 수가 동일하게 유지됩니다. 그러나 기본 보기가 변경되면 반환된 뷰의 요소에 액세스하면 정의되지 않은 동작이 발생할 수 있습니다.
drop
는 .의 반대입니다 take
.
이전에 "2)"로 표시된 코드는 파이프 구문 collection | drop(5)
과 함께 사용할 수 있습니다. 또는 함수 호출 구문 drop(collection, 5)
또는 drop(5)(collection)
.와 함께 사용할 수 있습니다.
예: drop
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v{1, 2, 3, 4, 5};
auto newView = std::views::drop(v, 3);
for (auto e : newView) // 4 5
{
std::cout << e << ' ';
}
std::cout << '\n';
auto numbers = std::views::iota(0) | std::views::take(10); // build a view of 10 integers
auto latterHalf = numbers | std::views::drop(5);
for (auto i : latterHalf)
{
std::cout << i << ' '; // 5 6 7 8 9
}
}
4 5
5 6 7 8 9
drop_while
지정된 조건과 일치하는 선행 요소가 삭제된 후에 남아 있는 범위의 요소가 포함된 뷰를 만듭니다.
1) template<ranges::viewable_range R, class P>
constexpr ranges::view auto drop_while(R&& rg, P&& predicate);
2) template<class P>
constexpr /*range adaptor closure*/ drop_while(P&& predicate);
매개 변수
R
범위의 형식입니다.
predicate
범위에서 삭제할 선행 요소를 결정하는 조건입니다.
rg
뷰를 만들 기본 범위입니다.
반환 값
조건자와 일치하는 선행 요소가 삭제될 때 남아 있는 요소로 구성된 A drop_while_view
입니다.
설명
조건자가 반환되는 즉시 요소 rg
삭제를 중지합니다 false
.
drop_while
는 .의 반대입니다 take_while
.
이전에 "2)"로 표시된 코드는 파이프 구문 collection | drop_while(predicate)
과 함께 사용할 수 있습니다. 또는 함수 호출 구문 drop_while(collection, predicate)
또는 drop_while(predicate)(collection)
.와 함께 사용할 수 있습니다.
예: drop_while
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
void print(auto&& v)
{
for (auto&& x : v)
{
std::cout << x << ' ';
}
std::cout << '\n';
}
int main()
{
std::vector<int> v{ 0, 1, 2, 3, -4, 5, 6 };
auto myView = std::views::drop_while(
v,
[](int i) {return i >= 0; });
print(myView); // -4 5 6
auto myView2 = v | std::views::drop_while(
[](int i) {return i < 5; });
print(myView2); // 5 6
}
-4 5 6
5 6
elements
elements_view
범위의 각 튜플과 유사한 값에 대해 선택한 인덱스의 보기인 을 만듭니다. 예를 들어 값 범위 std::tuple<string, int>
가 지정된 경우 각 튜플에서 모든 string
요소를 만듭니 elements_view
다.
template<ranges::viewable_range R, size_t N>
constexpr ranges::view auto elements<N>(R&& rg);
매개 변수
N
뷰에 포함할 각 튜플과 유사한 값 중에서 선택할 요소의 인덱스입니다.
R
기본 범위의 형식입니다.
rg
뷰를 만들 튜플과 유사한 값의 범위입니다.
반환 값
elements_view
컬렉션의 각 튜플과 유사한 값에 대해 선택한 인덱스로 구성된 값입니다.
예: elements
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <map>
#include <string>
int main()
{
std::map<std::string, int> cpp_standards
{
{"C++98", 1998},
{"C++03", 2003},
{"C++11", 2011},
{"C++14", 2014},
{"C++17", 2017},
{"C++20", 2020}
};
// Create an elements_view of all the string elements from each tuple
for (int const year : std::views::elements<1>(cpp_standards))
{
std::cout << year << ' '; // 2003 2011 2014 2017 1998 2020
}
std::cout << '\n';
// Another way, using |: create an elements_view of all the int elements from each tuple
for (auto&& name : cpp_standards | std::views::elements<0>)
{
std::cout << name << ' '; // C++03 C++11 C++14 C++17 C++98 c++20
}
}
2003 2011 2014 2017 1998 2020
C++03 C++11 C++14 C++17 C++98 c++20
empty
empty_view
요소가 없는 뷰를 만듭니다.
template<class T>
inline constexpr empty_view<T> empty{};
매개 변수
T
뷰에 있는 요소의 형식입니다. 요소가 없더라도 뷰에는 요소 형식이 필요합니다.
반환 값
empty_view
입니다.
설명
뷰 empty_view
가 필요하지만 해당 요소를 처리할 필요가 없는 코드를 호출할 때 유용할 수 있습니다.
예: empty
// requires /std:c++20 or higher
#include <ranges>
#include <iostream>
int main()
{
auto anEmptyView = std::views::empty<int>;
bool isNotEmpty = (bool)anEmptyView;
std::cout << boolalpha << isNotEmpty << "\n"; // false
}
false
filter
지정된 조건과 일치하는 범위의 요소가 포함된 뷰를 만듭니다.
1) template<ranges::viewable_range R, class P>
requires {filter_view(forward<R>(rg), forward<P>(predicate));}
constexpr ranges::view auto filter(R&& rg, P&& predicate);
2) template<class P>
constexpr /*range adaptor closure*/ filter(P&& predicate);
매개 변수
P
조건자의 형식입니다.
predicate
범위에 유지할 요소를 결정하는 조건입니다.
R
기본 범위의 형식입니다.
rg
뷰를 만들 범위입니다.
반환 값
조건자와 일치하는 범위의 요소를 포함하는 A filter_view
입니다.
설명
효율성을 위해 파이프|
와 transform
함께 사용할 filter
때 유지하려는 요소만 있도록 첫 번째 transform
작업을 수행 filter
합니다.
이전에 "2)"로 표시된 코드는 파이프 구문 collection | filter(predicate)
과 함께 사용할 수 있습니다. 또는 함수 호출 구문 filter(collection, predicate)
또는 filter(predicate)(collection)
.와 함께 사용할 수 있습니다.
예: filter
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
void print(auto&& v)
{
for (auto&& x : v)
{
std::cout << x << ' ';
}
std::cout << '\n';
}
int main()
{
std::vector<int> v{0, 1, 2, 3, -4, 5, 6};
auto myView = std::views::filter(v, [](int i) {return i < 5; });
print(myView); // 0 1 2 3 -4
auto myView2 = v | std::views::filter([](int i) {return i < 5; }); // pipe syntax
print(myView2); // 0 1 2 3 -4
}
0 1 2 3 -4
0 1 2 3 -4
iota
증가하는 값의 시퀀스가 포함된 뷰를 만듭니다. 시퀀스를 바인딩할 수 있습니다.
template<class V>
constexpr ranges::view auto iota(V&& startValue); // create an unbounded sequence of incrementing values
template<class V, class E>
constexpr ranges::view auto iota(V&& startValue, E&& endValue); // create a bounded sequence of incrementing values
매개 변수
E
끝 값의 형식입니다.
S
시작 값의 형식입니다.
startValue
시퀀스의 첫 번째 값입니다.
endValue
이 값은 시퀀스에 있는 마지막 값이 지난 값입니다. 예를 들어 std::views::iota(0, 5)
값이 있는 뷰를 생성합니다 0,1,2,3,4
.
반환 값
iota_view
증가하는 값의 시퀀스입니다.
설명
바인딩되지 않은 시퀀스의 경우 데이터 형식의 최대값에 도달한 후에 동작이 정의되지 않습니다.
예: iota
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
void print(auto&& v)
{
for (auto&& x : v)
{
std::cout << x << ' ';
}
std::cout << '\n';
}
int main()
{
// create an iota view with its range adaptor (preferred)
print(std::views::iota(0, 5)); // outputs 0 1 2 3 4
// create an iota_view class directly
std::ranges::iota_view letters{'a', 'f'};
print(letters); // a b c d e
}
0 1 2 3 4
a b c d e
istream
스트림의 요소에 대한 뷰를 만듭니다.
template <class Val>
views::istream<Val>(str);
매개 변수
str
스트림 개체입니다. 해당 형식은 .의 std::basic_istream
특수화에서 파생됩니다.
Val
스트림에서 추출할 요소의 형식입니다.
반환 값
이 범위 어댑터의 형식str
은 다음과 U
같습니다ranges::basic_istream_view<Val, typename U::char_type, typename U::traits_type>(str)
.
예: istream
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <sstream>
#include <vector>
int main()
{
std::istringstream doubles{"1.1 2.2 3.3 4.4 5.5"};
for (const auto& elem : std::views::istream<double>(doubles))
{
std::cout << elem << ' '; // 1.1 2.2 3.3 4.4 5.5
}
}
1.1 2.2 3.3 4.4 5.5
join
여러 범위의 모든 요소를 단일 보기로 결합하는 뷰를 만듭니다.
1) template <ranges::viewable_range R>
[[nodiscard]] constexpr ranges::view auto join(R&& rg) const noexcept;
2) inline constexpr /*range adaptor closure*/ join();
매개 변수
R
기본 범위의 형식입니다.
rg
뷰를 만들 범위입니다.
반환 값
기본 범위에 있는 모든 범위의 요소를 포함하는 A join_view
입니다.
예: join
#include <iostream>
#include <vector>
#include <ranges>
#include <string>
int main()
{
// a range of two ranges
std::vector<std::string> rangeOfRanges[2]{{"C++20", "contains:"}, {"ranges", "modules", "concepts & more."}};
for (const auto& elem : std::views::join(rangeOfRanges))
{
std::cout << elem << ' ';
}
}
C++20 contains: ranges modules concepts & more.
설명
이전에 "2)"로 표시된 코드는 파이프 구문 collection | join
과 함께 사용할 수 있습니다. 또는 함수 호출 구문과 함께 사용할 수 있습니다. join(collection)
keys
keys_view
컬렉션의 각 튜플과 유사한 값에 첫 번째 인덱스 만들기 이는 결합 컨테이너에서 키를 추출하는 데 유용합니다. 예를 들어 범위 std::tuple<string, int>
가 지정된 경우 각 튜플의 모든 요소로 구성된 뷰를 string
만듭니다.
template <ranges::viewable_range R>
constexpr auto keys(R&& rg);
매개 변수
R
기본 범위의 형식입니다.
반환 값
범위의 각 튜플과 유사한 값에 대한 첫 번째 인덱스로 구성된 A keys_view
입니다.
예: keys
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <map>
#include <string>
#include <vector>
int main()
{
// ========== extract keys from a map
std::map<std::string, int> cpp_standards
{
{"C++98", 1998},
{"C++03", 2003},
{"C++11", 2011},
{"C++14", 2014},
{"C++17", 2017},
{"C++20", 2020}
};
// Extract all of the keys from the map
for (std::string standards : std::views::keys(cpp_standards))
{
std::cout << standards << ' '; // C++03 C++11 C++14 C++17 C++98 C++20
}
std::cout << '\n';
// ========== Extract keys from a pair
std::vector<std::pair<std::string, int>> windows
{
{"Windows 1.0", 1985},
{"Windows 2.0", 1987},
{"Windows 3.0", 1990},
{"Windows 3.1", 1992},
{"Windows NT 3.1", 1993},
{"Windows 95", 1995},
{"Windows NT 4.0", 1996},
{"Windows 95", 1995},
{"Windows 98", 1998},
{"Windows 1.0", 1985},
{"Windows 2000", 2000}
};
// Another way to call the range adaptor is by using '|'
for (std::string version : windows | std::views::keys)
{
std::cout << version << ' '; // Windows 1.0 Windows 2.0 Windows 3.0 ...
}
}
C++03 C++11 C++14 C++17 C++98 C++20
Windows 1.0 Windows 2.0 Windows 3.0 Windows 3.1 Windows NT 3.1 Windows 95 Windows NT 4.0 Windows 95 Windows 98 Windows 1.0 Windows 2000
lazy_split
구분 기호에 따라 범위를 하위 범위로 분할합니다. 구분 기호는 단일 요소 또는 요소 뷰일 수 있습니다.
1) template<viewable_range R, class Pattern>
constexpr view auto lazy_split(R&& rg, Pattern&& delimiter);
2) template<class Pattern>
constexpr /*range adaptor closure*/ lazy_split(Pattern&& delimiter);
매개 변수
delimiter
단일 값 또는 범위를 분할할 위치를 지정하는 값 시퀀스입니다.
Pattern
구분 기호의 형식입니다.
R
분할할 범위의 형식입니다.
rg
분할할 범위입니다.
반환 값
lazy_split_view
하나 이상의 하위 범위를 포함하고 원래 범위를 delimiter
분할한 결과입니다.
설명
구분 기호는 결과의 일부가 아닙니다. 예를 들어 값2
의 범위를 1,2,3
분할하면 두 개의 하위 범위 1
와 .3
관련 어댑터입니다 split
. [split_view](split-view-class.md) and
lazy_split_view'의 주요 차이점은 다음과 같습니다.
View | 범위를 분할할 수 있습니다.const |
범위 반복기 |
---|---|---|
split_view |
아니요 | 지원 이상 forward_range |
lazy_split_view |
예 | input_range 이상 |
범위를 분할해야 하는 경우가 아니면 더 효율적이므로 선호 split_view
합니다 const
.
이전에 "2)"로 표시된 코드는 파이프 구문 collection | lazy_split(delimiter)
과 함께 사용할 수 있습니다. 또는 함수 호출 구문 lazy_split(collection, delimiter)
또는 lazy_split(delimiter)(collection)
.와 함께 사용할 수 있습니다.
예: lazy_split
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> rg{1, 2, 3, 1, 2, 3, 4, 5, 6};
// split on a single element
for (const auto& sub : rg | std::views::split(3))
{
// outputs:
// 1 2
// 1 2
// 4 5 6
for (const auto& elem : sub)
{
std::cout << elem << ' ';
}
std::cout << '\n';
}
// split on a sequence of elements
int delimiters[] = {2, 3};
for (const auto& subrange : std::views::split(rg, delimiters))
{
// outputs 1 1 4 5 6
for (auto& i : subrange)
{
std::cout << i << " ";
}
}
}
1 2
1 2
4 5 6
1 1 4 5 6
reverse
범위 요소의 뷰를 역순으로 만듭니다.
1) template<viewable_range R>
constexpr ranges::view auto reverse(R&& rg);
2) inline constexpr /*range adaptor closure*/ reverse();
매개 변수
R
역방향으로 지정할 기본 범위의 형식입니다.
rg
역방향 범위입니다.
반환 값
기본 범위의 요소를 역순으로 표시하는 뷰입니다. 반환된 뷰는 일반적으로는 아니지만 항상 특수화되는 reverse_view
것은 아닙니다. 구체적인 요건은 다음과 같습니다.
- 특수화
reverse_view
인 경우V
결과는 인수의 기본 뷰입니다. 이중 역방향은 no-op(작업 없음)입니다. - 폼
subrange<reverse_iterator<I>, reverse_iterator<I>>
이 있는 경우V
결과는 래핑되지 않은 반복기의 결과subrange
입니다. 이중 역방향은 no-op입니다. - 그렇지 않으면 결과는 .입니다
reverse_view
.
설명
이전에 "2)"로 표시된 코드는 파이프 구문 collection | reverse
과 함께 사용할 수 있습니다. 또는 함수 호출 구문과 함께 사용할 수 있습니다. reverse(collection)
예: reverse
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v{ 0, 1, 2, 3, -4, 5, 6 };
auto rv = v | std::views::reverse; // using the pipe syntax
for (auto &&e : rv) // outputs 6 5 -4 3 2 1 0
{
std::cout << e << ' ';
}
std::cout << '\n';
// using the range adaptor without using the pipe syntax
auto rv2 = std::views::reverse(v);
for (auto &&e : rv2) // outputs 6 5 -4 3 2 1 0
{
std::cout << e << ' ';
}
}
6 5 -4 3 2 1 0
6 5 -4 3 2 1 0
single
하나의 요소가 포함된 뷰인
template<class T>
constexpr ranges::view auto single(T&& t);
매개 변수
T
뷰에 있는 요소의 형식입니다.
t
뷰에 저장할 요소의 값입니다.
반환 값
single_view
포함되는 항목입니다.t
설명
이 보기는 하나 이상의 요소가 있는 뷰와 함께 제공해야 하는 코드를 호출하는 테스트 용도로 유용합니다.
예: single
// requires /std:c++20 or higher
#include <ranges>
#include <string>
#include <tuple>
#include <iostream>
int main()
{
auto sv = std::views::single(7);
std::cout << sv.front() << " " << *sv.data() << "\n"; // 7 7
auto sv2 = std::views::single(<std::tuple<double, std::string>{6502, "8-bit"});
std::cout << std::get<0>(sv2[0]) << " " << std::get<1>(sv2[0]) << "\n"; // 6502 8-bit
}
7 7
6502 8-bit
split
구분 기호에 따라 보기를 하위 범위로 분할합니다. 구분 기호는 단일 요소 또는 요소 시퀀스일 수 있습니다.
1) template<viewable_range R, class Pattern>
constexpr view auto split(R&& rg, Pattern&& delimiter);
2) template<class Pattern>
constexpr /*range adaptor closure*/ split(Pattern&& delimiter);
매개 변수
delimiter
단일 값 또는 범위를 분할할 위치를 지정하는 값 시퀀스입니다.
Pattern
구분 기호의 형식입니다.
R
분할할 기본 범위의 형식입니다.
rg
분할할 범위입니다.
반환 값
split_view
하나 이상의 하위 범위가 포함된 A입니다.
설명
구분 기호는 결과의 일부가 아닙니다. 예를 들어 값2
의 범위를 1,2,3
분할하면 두 개의 하위 범위 1
와 .3
관련 어댑터입니다 lazy_split
. 주요 차이점은 다음과 같습니다.split_view
lazy_split_view
View | 범위를 분할할 수 있습니다.const |
범위 유형 |
---|---|---|
split_view |
아니요 | 지원 이상 forward_range |
lazy_split_view |
예 | 지원 이상 input_range |
범위를 분할해야 하는 경우가 아니면 더 효율적이므로 선호 split_view
합니다 const
.
이전에 "2)"로 표시된 코드는 파이프 구문 collection | split(delimiter)
과 함께 사용할 수 있습니다. 또는 함수 호출 구문 split(collection, 5)
또는 split(5)(collection)
.와 함께 사용할 수 있습니다.
예: split
// requires /std:c++20 or later
#include <ranges>
#include <vector>
#include <iostream>
int main()
{
std::vector<int> rg{ 1, 2, 3, 1, 2, 3, 4, 5, 6 };
// split on a single element, 3
for (const auto& sub : rg | std::views::split(3))
{
// This prints out:
// 1,2
// 4,5,6
for (const auto& elem : sub)
{
std::cout << elem << ' ';
}
std::cout << '\n';
}
// split on a sequence of elements, 2,3
int delimiters[] = {2, 3};
for (const auto& subrange : std::views::split(rg, delimiters))
{
// outputs 1 1 4 5 6
for (auto& i : subrange)
{
std::cout << i << " ";
}
}
}
1 2
1 2
4 5 6
1 1 4 5 6
take
범위의 앞면에서 가져온 지정된 개수의 요소를 포함하는 뷰를 만듭니다.
1) template<ranges::viewable_range R>
constexpr ranges::view auto take(R&& rg, ranges::range_difference_type<R> count);
2) template<class DifferenceType>
constexpr /*range adaptor closure*/ take(DifferenceType&& count);
매개 변수
R
기본 범위의 형식입니다.
rg
뷰를 만들 범위입니다.
count
앞에서 가져올 요소의 수입니다 rg
.
반환 값
반환된 뷰는 일반적으로는 아니지만 항상 특수화되는 take_view
것은 아닙니다. 특별한 사항
- 의 특수화이거나 , ,
subrange
basic_string_view
iota_view
또는 둘 다sized_range
random_access_range
의 특수화empty_view
span
인 경우V
결과는 특수화입니다.V
- 그렇지 않으면 결과는 .입니다
take_view
.
설명
기존 rg
요소보다 더 많은 요소를 지정하면 모든 요소가 수행됩니다.
take
는 .의 반대입니다 drop
.
이전에 "2)"로 표시된 코드는 파이프 구문 collection | take(5)
과 함께 사용할 수 있습니다. 또는 함수 호출 구문 take(5, collection)
또는 take(5)(collection)
.와 함께 사용할 수 있습니다.
예: take
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::string s{ "abcdefg" };
auto myView = std::views::take(s, 3);
for (auto c : myView)
{
std::cout << c << ' '; // a b c
}
std::cout << std::endl;
for (auto c : s | std::views::take(3)) // pipe syntax
{
std::cout << c << ' '; // a b c
}
}
a b c
a b c
take_while
지정된 조건과 일치하는 범위의 선행 요소가 포함된 뷰를 만듭니다.
1) template<ranges::viewable_range R, class P>
constexpr ranges::view auto take_while(R&& rg, P&& predicate);
2) template<class P>
constexpr /*range adaptor closure*/ take_while(P&& predicate);
매개 변수
P
조건자의 형식입니다.
predicate
범위에서 복사할 선행 요소를 결정하는 조건입니다.
R
기본 범위의 형식입니다.
rg
뷰를 만들 범위입니다.
반환 값
범위에서 지정된 조건을 충족하는 첫 번째 count
요소로 구성된 A take_while_view
입니다.
설명
조건자가 반환 false
되거나 범위가 요소가 rg
다 떨어지면 요소의 제거를 중지합니다.
take_while
는 .의 반대입니다 drop_while
.
이전에 "2)"로 표시된 코드는 파이프 구문 collection | take_while(pred)
과 함께 사용할 수 있습니다. 또는 함수 호출 구문 take_while(collection, pred)
또는 take_while(pred)(collection)
.와 함께 사용할 수 있습니다.
예: take_while
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
void print(auto&& v)
{
for (auto&& x : v)
{
std::cout << x << ' ';
}
std::cout << '\n';
}
int main()
{
std::vector<int> v{ 0, 1, 2, 3, -4, 5, 6 };
auto myView = std::views::take_while(
v, [](int i) {return i >= 0; });
print(myView); // 0 1 2 3
print(v | std::views::take_while( // 0 1 2 3 -4
[](int i) {return i < 5; })); // pipe syntax
}
0 1 2 3
0 1 2 3 -4
transform
요소 뷰를 만듭니다. 각 요소는 지정된 범위의 요소 변환입니다.
1) template<viewable_range R, class F>
constexpr ranges::view auto transform(R&& rg, F&& fun);
2) template<class F>
constexpr /*range adaptor closure*/ transform(F&& fun);
매개 변수
F
요소를 변환할 함수 개체의 형식입니다.
R
기본 범위의 형식입니다.
fun
요소를 변환하는 함수입니다.
rg
뷰를 만들 범위입니다.
반환 값
의 변환된 요소를 rg
포함하는 A transform_view
입니다.
설명
효율성을 위해 작성할 transform
때 filter
첫 번째 filter
작업을 수행하여 transform
유지하려는 요소만 유지합니다.
이전에 "2)"로 표시된 코드는 파이프 구문 collection | transform(fun)
과 함께 사용할 수 있습니다. 또는 함수 호출 구문 transform(collection, fun)
또는 transform(fun)(collection)
.와 함께 사용할 수 있습니다.
예: transform
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
void print(auto&& v)
{
for (auto&& x : v)
{
std::cout << x << ' ';
}
std::cout << '\n';
}
int main()
{
std::vector<int> v{0, 1, 2, 3, -4, 5, 6};
auto myView = std::views::transform(v, [](int i) {return i * 2; });
print(myView); // 0 2 4 6 -8 10 12
print(v | std::views::transform( // 0 2 4 6 -8 10 12
[](int i) {return i * 2; })); // pipe syntax
}
0 2 4 6 -8 10 12
0 2 4 6 -8 10 12
values
values_view
컬렉션의 각 튜플과 유사한 값에 두 번째 인덱스로 구성된 값을 만듭니다. 이는 결합 컨테이너의 값을 보는 데 유용합니다. 예를 들어 값 범위 std::tuple<string, int>
가 지정된 경우 각 튜플의 모든 요소로 구성된 뷰를 int
만듭니다.
template <range::viewable_range R>
constexpr ranges::view auto values(R&& rg);
매개 변수
R
기본 범위의 형식입니다.
rg
튜플과 유사한 값의 기본 범위입니다.
반환 값
values_view
두 번째 인덱스에서 범위의 각 튜플과 유사한 값으로 빌드된 값입니다.
예: values
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <map>
#include <string>
#include <vector>
int main()
{
// ========== working with a map
std::map<std::string, int> cpp_standards
{
{"C++98", 1998},
{"C++03", 2003},
{"C++11", 2011},
{"C++14", 2014},
{"C++17", 2017},
{"C++20", 2020}
};
// Extract all of the years from the map
for (int years : std::views::values(cpp_standards))
{
std::cout << years << ' '; // 2003 2011 2014 2017 1998 2020
}
std::cout << '\n';
// ========== working with pairs
std::vector<std::pair<std::string, int>> windows
{
{"Windows 1.0", 1985},
{"Windows 2.0", 1987},
{"Windows 3.0", 1990},
{"Windows 3.1", 1992},
{"Windows NT 3.1", 1993},
{"Windows 95", 1995},
{"Windows NT 4.0", 1996},
{"Windows 95", 1995},
{"Windows 98", 1998},
{"Windows 1.0", 1985},
{"Windows 2000", 2000}
};
// Another way to call the range adaptor by using '|'
// Create a values_view that contains the year from each pair
for (int years : windows | std::views::values)
{
std::cout << years << ' '; // 1985 1987 1990 1992 ...
}
}
2003 2011 2014 2017 1998 2020
1985 1987 1990 1992 1993 1995 1996 1995 1998 1985 2000
범위 어댑터 형식 별칭
all_t
반환되는 뷰의 형식을 all
제공합니다.
template <ranges::viewable_range R>
using all_t = decltype(views::all(std::declval<R>()));
매개 변수
R
기본 범위의 형식입니다.
반환 값
반환되는 all
뷰의 형식입니다 decltype(views::all(std::declval<R>()))
.
예: all_t
#include <ranges>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v = {1,2,3,4,5,6,7,8,9,10};
auto myView = std::views::all(v);
std::views::all_t<decltype((v))> &viewType = myView;
}