개념적으로 constexpr은 값이 상수임을 알릴 뿐만 아니라 컴파일 타임에 알려진다는 점을 나타낸다.

 

객체에 constexpr이 적용되면 상수화되고 해당 값은 컴파일 타임에 알려진다. 하지만 const는 그럴거라는 보장이 없다.

모든 constexpr 객체는 const이지만 모든 const 객체는 constexpr인것은 아니다.

 

다만 이 개념이 함수에 적용되면 약간 다르게 적용된다.

constexpr 함수는 컴파일 타임의 상수를 인수로 호출한 경우에는 컴파일 타임에 상수를 산출하지만 런타임에 산출된 값으로 호출하면 런타임에 값을 산출한다.

 

constexpr 함수에 대한 올바른 관점

◾ 컴파일 타임 상수를 요구하는 문맥에 constexpr 함수를 사용할 수 있다. 인수의 값이 컴파일 타임에 알려진다면 결과는 컴파일 타임에 계산되고 컴파일 타임에 알려지지 않는다면 코드의 컴파일이 거부된다.

◾ 컴파일 타임에 알려지지 않는 하나 이상의 값들로 constexpr 함수를 호출하면 보통의 함수처럼 작동한다. 별도의 함수로 나눌 필요 없이 하나의 constexpr  함수를 두 가지 용도로 사용하면 된다.

 

constexpr int pow(int base, int exp) noexcept {
    ...
}

constexpr auto cnumConds = 5;
std::array<int, pow(3, numConds)> results;

함수에 constexpr이 붙었다고 해서 결과값이 반드시 const인 것은 아니다.

 

constexpr int pow(int base, int exp) noexcept { // C++11
    return (exp == 0 ? 1 : base * pow(base, exp - 1));
}

C++11에서 constexpr 함수는 실행 가능 문장이 많아야 하나만 있어야 한다. 보통은 return문이 될 것이고 삼항연산자와 재귀를 이용해서 함수의 표현력을 확장시킬 수 있다.

 

constexpr int pow(int base, int exp) noexcept { // C++14
    auto reuslt = 1;
    for (int i = 0; i < exp; ++i) result *= base;
    
    return result;
}

C++14는 제약이 상당히 느슨해져서 실행 가능 문장이 여러줄이어도 괜찮다. 다만 반드시 리터럴 타입들을 받고 돌려주어야 한다.

 

 

class Point {
public:
    constexpr Point(double xVal = 0, double yVal = 0) noexcept : x(xVal), y(yVal) {}
    constexpr double xValue() const noexcept { return x; }
    constexpr double yValue() const noexcept { return y; }
};
...
constexpr Point p1(9.4, 27.7); // OK
constexpr Point p2(28.8, 5.3); // OK

생성자를 constexpr로 선언할 수 있는 이유는 주어진 인수들이 컴파일 타임에 알려진다면 생성된 객체의 멤버 변수들 역시 컴파일 타임에 알려질 수 있기 때문이다.

컴파일 타임에 알려진 값으로 초기화된 객체는 getter역시 constexpr이 될 수 있다. 연쇄적으로 다 가능해진다.

 

class Point {
public:
    ...
    constexpr void setX(double newX) noexcept { x = newX; } // C++14
    constexpr void setY(double newY) noexcept { y = newY; }
};

만약 setter를 constexpr로 구현한다면 C++11에서는 구현할 수 없다. constexpr 멤버 함수는 암묵적으로 const로 선언되고 void타입은 리터럴이 아니기 때문이다.

 

연산들을 컴파일 타임으로 옮길수록 실행시간은 빨라지지만 컴파일 시간이 길어지게 된다.

 

constexpr역시 가능하면 항상 사용하는것이 좋다.

덧붙여서 constexpr 함수에서는 입출력 문장들이 허용되지 않는다.

 

◾ constexpr 객체는 const이며, 컴파일 도중에 알려지는 값들로 초기화된다.

◾ constexpr 함수는 그 값이 컴파일 도중에 알려지는 인수들로 호출하는 경우에는 컴파일 타임 결과를 산출한다.

◾ constexpr 객체나 함수는 비constexpr 객체나 함수보다 광범위한 문맥에서 사용할 수 있다.

◾ constexpr은 객체나 함수의 인터페이스의 일부이다.

+ Recent posts