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

난이도 중 해설 보기 →

결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커 (A)(B) 는 주목 위치 힌트다.

결함 코드 · C++
// 주제: 가변 인자 템플릿(variadic templates), 파라미터 팩 전개, fold expression.
//
// 과제:
//  1) 아래 프로그램의 출력을 정확히 예측하라.
//  2) sum_recursive(재귀 전개)와 sum_fold(폴드 표현식)가 각각 어떻게
//     인스턴스화되는지, 컴파일러가 파라미터 팩을 어떻게 펼치는지 설명하라.
//  3) print_all 의 (expr, ...) 콤마 폴드가 인자 순서를 어떻게 보장하는지,
//     빈 팩(sizeof...(Args)==0)에서 각 함수가 어떻게 동작하는지 설명하라.
//  4) count_args 가 컴파일 타임 상수인 이유를 설명하라.

#include <iostream>
#include <string>

// (1) 재귀적 파라미터 팩 전개
template <typename T>
T sum_recursive(T v) { return v; }

template <typename T, typename... Rest>
T sum_recursive(T first, Rest... rest) {
    return first + sum_recursive(rest...);
}

// (2) 단항 우측 폴드: (a1 + (a2 + (... + an)))
template <typename... Args>
auto sum_fold(Args... args) {
    return (args + ...);
}

// (3) 콤마 폴드로 각 인자에 부수효과(출력)를 순서대로 적용
template <typename... Args>
void print_all(const Args&... args) {
    std::size_t i = 0;
    ((std::cout << (i++ ? "," : "") << args), ...);
    std::cout << "\n";
}

// (4) 인자 개수: 컴파일 타임 상수
template <typename... Args>
constexpr std::size_t count_args(const Args&...) {
    return sizeof...(Args);
}

int main() {
    std::cout << sum_recursive(1, 2, 3, 4) << "\n";       // int 합
    std::cout << sum_fold(1, 2, 3, 4) << "\n";            // int 합
    std::cout << sum_fold(std::string("a"),
                          std::string("b"),
                          std::string("c")) << "\n";      // string 접합(우측 폴드)
    print_all(10, 20, 30);                                // 순서 보장 출력
    print_all("x", "y");
    constexpr std::size_t n = count_args(1, 2.0, 'c', "s");
    std::cout << n << "\n";                                // 컴파일 타임 개수
    return 0;
}
내 리뷰 · C++
내 답안 · 자동 저장

작성 후 위 해설 보기에서 모범 해설과 대조하세요.