constexpr와 consteval
Coddy C++ 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 104개 중 87번째.
C++는 런타임이 아닌 컴파일 타임에 연산이 수행되도록 허용하며, 이는 성능을 크게 향상시킬 수 있습니다. constexpr 키워드(C++11)와 consteval 키워드(C++20)는 표현식이 평가되는 시점을 제어할 수 있게 해줍니다.
constexpr 함수는 상수 인자가 주어지면 컴파일 시간에 평가될 수 있지만, 상수가 아닌 입력이 주어지면 런타임에도 실행될 수 있습니다:
#include <iostream>
constexpr int square(int n) {
return n * n;
}
int main() {
constexpr int compileTime = square(5); // 컴파일 시간에 평가됨
int x = 7;
int runtime = square(x); // 런타임에 평가됨
std::cout << compileTime << "\n"; // 25
std::cout << runtime << "\n"; // 49
}컴파일 시간 평가를 보장해야 할 때는 consteval을 사용하세요. consteval 함수는 반드시 상수를 생성해야 하며, 런타임 값으로 이를 호출하는 것은 컴파일 오류입니다:
consteval int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
int main() {
constexpr int result = factorial(5); // 성공: 120이 컴파일 시간에 계산됨
// int x = 5;
// int bad = factorial(x); // 오류: x는 상수가 아님
}또한 변수와 클래스 생성자에도 constexpr을 사용할 수 있어, 전체 객체를 컴파일 시간에 생성할 수 있습니다. 이는 룩업 테이블, 설정 값 또는 프로그램 실행 중에 변경되지 않는 모든 데이터에 특히 유용합니다.
챌린지
쉬움코드를 세 개의 파일로 나누어 구성합니다:
MathUtils.h: 컴파일 타임 수학 함수를 정의합니다.다음 함수들을 생성하세요:
cube—int를 인자로 받아 그 세제곱(n * n * n)을 반환하는constexpr함수triangularNumber— n * (n + 1) / 2 공식을 사용하여 n번째 삼각수를 계산하는constexpr함수. 이 함수는 항상 컴파일 타임에 평가되어야 합니다.sumOfSquares— 두 개의 정수를 인자로 받아 그 제곱의 합(a*a + b*b)을 반환하는constexpr함수
Config.h: 컴파일 타임 상수를 사용하여 설정 구조체를 생성합니다.세 개의 정수
width,height,depth를 인자로 받는constexpr생성자를 가진Config구조체를 정의하세요. 이 값들을 public 멤버로 저장합니다. 또한 width * height * depth를 반환하는volume()이라는constexpr메서드를 추가하세요.구조체 아래에 10, 20, 5 값으로 초기화된
DEFAULT_CONFIG라는constexpr전역 상수를 생성하세요.main.cpp: 런타임 값을 나타내는 두 개의 정수를 입력받습니다.먼저,
constexpr변수를 생성하여 컴파일 타임 평가를 보여줍니다:cube(4)를 constexpr 변수에 저장하고 출력합니다:Cube of 4: [value]triangularNumber(10)을 constexpr 변수에 저장하고 출력합니다:10th triangular number: [value]- 기본 설정의 부피를 출력합니다:
Default volume: [value]
그 다음, 입력받은 두 값을 사용하여
constexpr함수가 런타임에도 작동할 수 있음을 보여줍니다:- 첫 번째 입력값으로
cube()를 호출하고 출력합니다:Cube of [input]: [result] - 두 입력값으로
sumOfSquares()를 호출하고 출력합니다:Sum of squares: [result]
예를 들어, 입력값이 3과 4인 경우:
Cube of 4: 64
10th triangular number: 55
Default volume: 1000
Cube of 3: 27
Sum of squares: 25입력값이 5와 12인 경우:
Cube of 4: 64
10th triangular number: 55
Default volume: 1000
Cube of 5: 125
Sum of squares: 169치트 시트
C++는 constexpr (C++11) 및 consteval (C++20) 키워드를 사용하여 컴파일 시간(compile time)에 연산을 수행할 수 있도록 허용합니다.
constexpr 함수는 상수 인자와 함께 사용될 때 컴파일 시간에 평가될 수 있지만, 상수가 아닌 입력과 함께 사용될 때는 런타임에도 실행됩니다:
constexpr int square(int n) {
return n * n;
}
constexpr int compileTime = square(5); // 컴파일 시간에 평가됨
int x = 7;
int runtime = square(x); // 런타임에 평가됨consteval 함수는 반드시 컴파일 시간에 평가되어야 합니다. 런타임 값으로 이 함수를 호출하면 컴파일 오류가 발생합니다:
consteval int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
constexpr int result = factorial(5); // OK: 컴파일 시간에 계산됨
// int x = 5;
// int bad = factorial(x); // 오류: x는 상수가 아님변수, 클래스 생성자, 메서드에 constexpr을 사용하여 컴파일 시간 객체 생성을 활성화할 수 있습니다:
struct Config {
int width, height, depth;
constexpr Config(int w, int h, int d)
: width(w), height(h), depth(d) {}
constexpr int volume() const {
return width * height * depth;
}
};
constexpr Config config(10, 20, 5); // 컴파일 시간에 생성됨직접 해보기
#include <iostream>
#include "MathUtils.h"
#include "Config.h"
using namespace std;
int main() {
// 입력으로부터 두 개의 정수 읽기
int input1, input2;
cin >> input1;
cin >> input2;
// TODO: 컴파일 타임 평가 시연
// cube(4)를 저장하는 constexpr 변수를 생성하고 "Cube of 4: [value]"를 출력
// TODO: triangularNumber(10)을 저장하는 constexpr 변수 생성
// 그리고 "10th triangular number: [value]"를 출력
// TODO: 기본 설정의 볼륨 출력: "Default volume: [value]"
// TODO: constexpr 함수의 런타임 사용 시연
// input1으로 cube()를 호출하고 "Cube of [input1]: [result]"를 출력
// TODO: 두 입력값으로 sumOfSquares() 호출
// 그리고 "Sum of squares: [result]"를 출력
return 0;
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.