const

 

  • const는 컴파일 또는 런타임에 결정되는 상수를 대상으로 사용되는 키워드입니다.




constexpr(constant expression)

 

  • constexpr은 컴파일 타임에 결정되는 상수를 대상으로 사용되는 키워드입니다.

 

  • constexpr은 const와 다르게 어떠한 상수식에서도 사용될 수 있습니다.




const와 constexpr 변수 초기화

int main() {
    int num1 = 0;

  const int num2 = num1 + 1;

  // 컴파일 에러
    constexpr int num3 = num1 + 1;

    return 0;
}

 

  • const는 어떻게 사용하느냐에 따라서 런타임에 초기화될 수 있습니다. 그렇기 때문에 확실하게 컴파일 타임에 초기화되어 보다 나은 런타임 성능을 얻기 위해서는 constexpr을 사용하는 것이 좋습니다.




constexpr 함수

 

#include <iostream>

using namespace std;

constexpr int Factorial(int n) {
    int total = 1;
    for (int i = 1; i <= n; i++) {
        total *= i;
    }

    return total;
}

template <int N>
struct A {
    int operator()() { return N; }
};

int main() {
    A<Factorial(10)> a;

    std::cout << a() << std::endl;
}

 

  • 함수 return 타입에 constexpr을 사용하여 컴파일 타임 상수를 return 하도록 정의할 수 있습니다. 이 처럼 컴파일 타임 상수를 반환하는 함수를 정의하여 상수가 필요한 템플릿 인자라던가 배열의 길이를 정의할 때 사용할 수 있습니다.

 

  • constexpr 함수를 호출할 때 반드시 컴파일 타임 상수를 인자로 전달해야 컴파일 타임 상수를 return 합니다. 만약, 컴파일 타임 상수가 아닌 변수를 인자로 전달하여 호출한다면 정상적으로 호출은 되지만, 컴파일 타임 상수를 return하진 않습니다.




constexpr 함수의 조건

 

  • goto문 사용 불가

 

  • try/catch 사용 불가(C++ 20 부터는 사용 가능하다고 합니다.)

 

  • 리터럴 타입이 아닌 변수 정의 불가

 

  • 초기화되지 않은 변수 정의 불가

 

  • 로직 중간에 constexpr이 아닌 함수를 호출 불가




inline 함수와 constexpr 함수

 

  • 함수 inline은 컴파일러의 판단에 의해서 함수 호출부가 함수의 로직으로 치환되는 것을 말합니다.

 

  • constexpr 함수는 컴파일러의 판단에 의해서 컴파일 타임에 로직을 수행하여 결괏값으로 되는 것을 말합니다.




최적화 컴파일

 

  • 최적화 컴파일을 껐을 경우 inline 함수는 절대로 inline되지 않지만, constexpr은 최적화 컴파일과는 별개로 컴파일러의 판단에 의해서 컴파일 상수를 return 합니다.




constexpr 생성자

 

#include <iostream>

using namespace std;

class Vector {
public:
    constexpr Vector(int x, int y) : x_(x), y_(y) {}

    constexpr int x() const { return x_; }
    constexpr int y() const { return y_; }

private:
    int x_;
    int y_;
};

constexpr Vector AddVec(const Vector& v1, const Vector& v2) {
    return { v1.x() + v2.x(), v1.y() + v2.y() };
}

template <int N>
struct A {
    int operator()() { return N; }
};

int main() {
    constexpr Vector v1{ 1, 2 };
    constexpr Vector v2{ 2, 3 };

    // constexpr 객체의 constexpr 멤버 함수는 역시 constexpr!
    A<v1.x()> a;
    std::cout << a() << std::endl;

    // AddVec 역시 constexpr 을 리턴한다.
    A<AddVec(v1, v2).x()> b;
    std::cout << b() << std::endl;
}

 

  • constexpr 생성자의 경우 constexpr 함수에 적용되는 제약 조건들이 모두 적용됩니다. 또한 constexpr 생성자의 인자들은 반드시 리터럴 타입이여야만 하고, 해당 클래스는 다른 클래스를 상속 받을 수 없습니다.

 

  • constexpr 생성자를 가지고있어야만 constexpr 객체를 생성할 수 있습니다. 그리고 constexpr 객체의 constexpr 멤버 함수만이 컴파일 타임 상수를 return할 수 있습니다.




+ Recent posts