← 문제로

38. 가변 인자 템플릿·파라미터 팩 전개·fold expression

난이도 중
내 리뷰 · C++
해설 · C++

해설 — 가변 인자 템플릿·파라미터 팩 전개·fold expression

난이도: 중상

요약

가변 인자 템플릿은 파라미터 팩을 컴파일 타임에 펼쳐 임의 개수 인자를 타입 안전하게 처리한다. 전개 방식은 두 가지다: (1) 재귀(하나 벗겨 나머지로 재귀), (2) C++17 fold expression((pack op ...))으로 한 표현식에 접기. 출력은 다음과 같다.

10
10
abc
10,20,30
x,y
4

핵심 개념

  • 파라미터 팩 typename... Args / Args... args: 0개 이상의 타입/값 묶음. sizeof...(Args) 로 개수를 컴파일 타임에 얻는다.
  • 팩 전개(expansion) pattern...: 팩을 콤마로 구분해 펼친다. sum_recursive(rest...)rest 의 각 원소를 인자로 나열.
  • fold expression(C++17):
    • 단항 우측 폴드 (E op ...)E1 op (E2 op (... op EN))
    • 단항 좌측 폴드 (... op E)((E1 op E2) op ...) op EN
    • 이항 폴드 (E op ... op init) 는 빈 팩에서 init 을 결과로.

단계별 내부 동작

  1. sum_recursive(1,2,3,4) → 10: 컴파일러가 sum_recursive<int,int,int,int>1 + sum_recursive<int,int,int>(2,3,4) → … → 기저 sum_recursive<int>(4)=4. 즉 4개의 서로 다른 오버로드가 인스턴스화되어 1+(2+(3+4)) 로 접힌다. 각 재귀 단계가 별도 함수 인스턴스라 코드 크기가 인자 수에 비례.
  2. sum_fold(1,2,3,4) → 10: (args + ...) 는 단항 우측 폴드 1 + (2 + (3 + 4)). 재귀 없이 하나의 함수 본문에서 표현식 트리로 전개된다.
  3. sum_fold("a","b","c") → "abc": 우측 폴드라 a + (b + c). std::string operator+ 로 접합. 좌측 폴드였다면 (a+b)+c 로 결합 순서가 달라진다(문자열은 결과 동일하지만 부동소수점 합처럼 결합 순서가 값에 영향 주는 타입도 있다).
  4. print_all(10,20,30)10,20,30: ((std::cout << sep << args), ...)콤마 연산자 폴드. 콤마 연산자는 좌→우 평가 순서와 시퀀스 포인트를 보장하므로 인자가 선언 순서대로 출력된다. i++ 로 첫 항만 구분자 생략.
  5. count_args(1,2.0,'c',"s") → 4: sizeof...(Args) 는 순수 컴파일 타임 상수 → constexpr std::size_t n 초기화 가능. 인자 값은 무시하고 팩 크기만 센다.

흔한 오해·함정

  • 폴드 방향 혼동: (args + ...) 는 우측 폴드다. 좌측을 원하면 (... + args). 뺄셈·나눗셈처럼 비결합 연산에서 결과가 달라진다.
  • 빈 팩: (args + ...) 에 인자가 0개면 컴파일 오류(단항 폴드는 &&,||,, 만 빈 팩 허용). 안전하려면 이항 폴드 (args + ... + 0) 로 초기값을 준다.
  • 콤마 폴드의 평가 순서: (f(args), ...) 는 순서가 보장되지만, printf("%d%d", args...) 같은 함수 호출 인자 전개는 인자 평가 순서가 미지정이다 — 부수효과 순서에 의존하면 안 된다.
  • 재귀 전개의 코드 팽창: 인자 수만큼 오버로드가 생겨 컴파일 시간·바이너리 증가. fold 나 if constexpr 로 단일 본문화하면 개선.

면접 포인트

  • 재귀 전개 vs fold expression 의 차이(인스턴스화 개수·가독성·빈 팩 처리)와, C++17 이전에는 왜 재귀/initializer_list 트릭을 썼는지.
  • 좌측/우측 폴드의 결합 순서가 실제 결과에 영향을 주는 사례(부동소수점 누적, 비가환 연산).
  • 콤마 폴드로 "각 인자에 순서대로 부수효과"를 안전하게 적용하는 관용구와, 함수 인자 전개의 평가 순서 미지정 함정.