[모던C++입문] 5.1 컴파일러가 계산하도록 만들기

5 메타 프로그래밍

5.1 컴파일러가 계산하도록 만들기

  • 컴파일 타임 계산은 두가지 방법이 있다.
    • 템플릿 메타 함수(Meta-Function)를 사용
    • constexpr을 사용 (C++11)

컴파일 타임 함수

constexpr long fibonacci(long n)
{
    return n <= 2 ? 1 : fibonacci(n-1) + fibonacci(n-2);
}
  • constexpr에 들어갈 수 있는 문장은 제한적
    • 함수 외부에서는 읽거나 쓸수 없다. 사이드 이펙트가 없다.
    • 변수를 포함할 수 없다.
    • if 또는 for와 같은 제어문을 포함할 수 없다.
    • 단일 계산문만 포함할 수 있다.
    • constexpr인 함수만 호출할 수 있다.
  • 템플릿 메타 함수와 비교시
    • 부동소수점 타입을 전달할 수 있다.
    • 사용자 정의 타입을 처리할 수도 있다.
    • 타입 검출을 사용할 수 있다.
    • 멤버 함수를 정의할 수 있다.
    • 조건문을 사용할 수 있다.
    • 런타임 인수를 사용해 함수를 호출할 수 있다.

확장된 컴파일 타임 함수 (C++14)

  • void함수가 가능해짐
    • constexpr void square(int& x) { x *= x; }
  • 다음 조건을 만족하는 지역변수
    • 초기화되어 있다.
    • static이 아니며, thread 저장기간도 없다
    • 리터럴 타입을 갖는다.
  • 다음을 제외한 제어문
    • goto
    • 어셈블리 코드 (asm블록)
    • try 블록
//C++14에서만 가능
template<typename T>
constexpr T power(const T& x, int n)
{
    T r(1);
    while(--n > 0)
        r *= x;
    return r;
}

소수판정

// 1은 소수가 아니다
// 2를 제외한 짝수는 소수가 아니다.
// 1보다 큰 홀수와 자기 자신보다 작은수로 나눌수 없는가?
// 자신의 제곱근 값보다 낮은수까지만 검사해도 된다
const bool is_prime(int i)
{
    if( i == 1)
        return false;
    if( i % 2 == 0 )
        return i == 2;
    int max_check = static_cast<int>(sqrt(i)) + 1;
    for( int j = 3; j < max_check; j += 2 )
        if( i % j == 0 )
            return false;
    return true;
}

상수는 어떻게 불변 상태가 되는가?

const int i = something;

  • 위 코드는 두가지 불변성을 설정
    • 프로그램 실행 중에 개체를 변경할 수 없다.
    • 컴파일 타임에 이 값을 이미 알고 있다.
  • something이 리터럴이라면 컴파일 동안 사용가능
  • 변수를 const 개체에 할당하는 경우 컴파일하는 동안 사용 불가
const long i = 7, j - 8;

template<long N>
struct static_long
{
    struct const long value = N;
};

const long k = i + j;
static_long<k> = sk;

long ll;
cin >> ll;
const long cl = ll;
static_long<cl> scl;    //오류
반응형

댓글

Designed by JB FACTORY