[C++23 새기능 소개] std::views::repeat와 std::views::repeat_n

C++23에서는 범위(Range) 라이브러리를 더욱 강화하기 위해 다양한 뷰(View) 어댑터가 추가되었습니다. 그중 std::views::repeatstd::views::repeat_n는 특정 값을 무한히 반복하거나, 지정된 횟수만큼 반복하는 시퀀스를 손쉽게 만들 수 있도록 해주는 뷰 어댑터입니다. 이를 통해 반복적인 데이터 소스를 간편하게 생성할 수 있으며, 다른 범위 어댑터와 결합하여 여러 가지 흥미로운 데이터 처리 파이프라인을 구성할 수 있습니다.

 

이번 글에서는 std::views::repeat와 std::views::repeat_n의 개념과 사용법, 그리고 이전 방식과 비교하여 어떠한 개선점을 제공하는지 알아보겠습니다.

 

std::views::repeat란 무엇인가요?

  • std::views::repeat(value): 단일 값 value를 무한히 반복하는 범위를 생성합니다.
    예를 들어, std::views::repeat(42)를 하면 [42, 42, 42, ...]와 같은 무한 시퀀스를 얻을 수 있습니다.

이 무한 시퀀스는 게으른(lazy) 방식으로 값이 필요할 때마다 같은 값을 생성하므로, 메모리 오버헤드 없이 무한 시퀀스를 표현할 수 있습니다. 물론 실제 프로그램에서는 무한 시퀀스를 모두 소비하지 않도록 다른 연산자(take, drop 등)와 결합해야 합니다.

std::views::repeat_n란 무엇인가요?

  • std::views::repeat_n(value, n): 단일 값 value를 정확히 n번 반복하는 유한 시퀀스를 생성합니다.
    예를 들어, std::views::repeat_n(42, 3)를 하면 [42, 42, 42]라는 유한 시퀀스를 얻을 수 있습니다.

이로써 특정한 값이나 상수를 여러 번 반복하는 범위를 손쉽게 만들 수 있어, 테스트용 데이터나 일정한 패턴을 생성하는데 유용합니다.

이전 버전에서는 어떻게 했나요?

C++20까지는 특정 값을 반복하는 시퀀스를 만들기 위해 다음과 같은 방법을 사용했습니다.

예제: 기존 방식(C++20까지)

#include <vector>
#include <iostream>

// 특정 값을 n번 반복하는 벡터 생성
int main() {
    int value = 42;
    int n = 3;

    std::vector<int> vec(n, value); // 벡터 생성자로 해결
    // 하지만 파이프라인에서 repeat 형태의 범위를 만들려면 직접 range 생성 필요
    // 무한 시퀀스는 별도 이터레이터 래퍼 만들거나 해야 함.

    for (int x : vec) {
        std::cout << x << ' ';
    }
    // 출력: 42 42 42
    return 0;
}
  • 무한 반복 시퀀스를 만들려면 사용자 정의 이터레이터 작성 혹은 while(true)루프 등 비우아한 방법 필요.

C++23의 std::views::repeat 사용 예제

#include <ranges>
#include <iostream>

int main() {
    // 무한히 10을 반복하는 시퀀스
    auto infinite_tens = std::views::repeat(10);

    // 무한 시퀀스에서 처음 5개 원소만 취하기
    for (int x : infinite_tens | std::views::take(5)) {
        std::cout << x << ' '; // 출력: 10 10 10 10 10
    }

    return 0;
}
  • repeat와 take를 결합해 원하는 개수만큼 무한 시퀀스 소비 가능.

C++23의 std::views::repeat_n 사용 예제

#include <ranges>
#include <iostream>

int main() {
    // 42를 3번 반복하는 시퀀스
    auto three_times_42 = std::views::repeat_n(42, 3);

    for (int x : three_times_42) {
        std::cout << x << ' '; // 출력: 42 42 42
    }

    return 0;
}
  • 한 번의 호출로 n번 반복하는 유한 시퀀스 생성.

어떻게 좋아졌나요?

  • 코드 간결성: 별도의 컨테이너 생성이나 사용자 정의 이터레이터 없이 단일 값 반복 시퀀스 생성 가능.
  • 가독성 향상: repeat와 repeat_n이라는 직관적인 이름에서 의도가 명확히 드러남.
  • 함수형 프로그래밍 스타일 강화: 다른 뷰(transform, filter, take, drop)와 결합해 복잡한 데이터 파이프라인을 단순화.
  • 메모리 효율성: 값 하나를 반복하므로, 큰 메모리 비용 없이 게으른 평가로 시퀀스를 표현 가능.

다른 뷰와의 조합 예시

#include <ranges>
#include <iostream>

int main() {
    // "Hello" 문자열을 5번 반복 후, 모두 대문자로 변환
    auto repeated_hello = std::views::repeat_n("Hello", 5)
                         | std::views::transform([](auto s) {
                             std::string upper;
                             for (char c : std::string(s)) {
                                 upper.push_back(static_cast<char>(std::toupper(static_cast<unsigned char>(c))));
                             }
                             return upper;
                           });

    for (auto str : repeated_hello) {
        std::cout << str << '\n';
    }
    // 출력:
    // HELLO
    // HELLO
    // HELLO
    // HELLO
    // HELLO

    return 0;
}
  • repeat_n과 transform을 결합해 반복된 문자열 변환 처리도 간단히 표현.

주의 사항

  • 무한 시퀀스 주의: repeat는 무한 시퀀스를 생성하므로, take나 drop 등을 사용해 제한하지 않으면 무한 루프 가능.
  • C++23 지원 여부: C++23 기능이므로, 해당 기능 지원 컴파일러 및 표준 라이브러리 필요.

요약

C++23의 std::views::repeat와 std::views::repeat_n은 단일 값을 무한히 또는 지정 횟수만큼 반복하는 시퀀스를 손쉽게 생성하는 뷰 어댑터입니다. 이를 통해 테스트용 데이터 생성, 패턴 반복, 파이프라인과 결합한 데이터 변환 등 다양한 시나리오를 가독성 높게 구현할 수 있으며, 메모리 효율적이고 함수형 프로그래밍 스타일에 어울리는 코드를 작성할 수 있습니다.

 

 

참고 자료:

반응형