constexpr
일반적인 const와 비슷한데 value나 연산을 컴파일 타임에 계산할 수 있으면 컴파일 타임에 계산하라는 의미이다.
Example Code
int cal(int a, int b, int c)
{
return a*b+c;
}
int main()
{
int a = 3;
int b = 5;
int c = 2;
int d = cal(a,b,c);
}
위와 같은 코드를 만든 순간 이미 컴파일러는 a,b,c의 값을 알고 있고 그 계산식 또한 알고 있다. 즉, 답이 컴파일 시간에 정해져 있다는 뜻이다. 이를 굳이 함수로 만들고 값을 넘기면서 실행할 필요없이 컴파일 시간에 계산하여 출력하면 더 빠르게 동작할 수 있을 것이다.
Compiler Explorer에서 확인해보자.

어셈블리를 보면 각각의 변수에 해당하는 곳에 3,5,2를 넣은 뒤 정의된 Cal 함수를 호출해서 결과값을 구했다. 하지만 constexpr을 활용하면 결과값 17을 바로 어셈블리에서 확인 가능하다.
constexpr int cal(int a, int b, int c)
{
return a*b+c;
}
int main()
{
constexpr int a = 3;
constexpr int b = 5;
constexpr int c = 2;
int d = cal(a,b,c);
}

어셈블리를 보면 Cal 함수 호출없이 d 위치에 바로 계산 결과값 17이 들어간 것을 볼 수 있다. 프로그램은 훨씬 더 간단해졌다.
constexpr int cal(int a, int b, int c)
{
// 1) if 연산
if (a % 2 == 0)
return b;
return c;
// 2) for Loop
int localSum = 0;
for (int i = 0; i < a; i++)
{
localSum += (i*b+c);
}
return localSum;
}
a*b+c와 같은 간단한 연산뿐 아니라 다음과 같은 연산들도 컴파일 시간에 계산이 가능하다. 이러한 constexpr은 간단한 함수, 변수 말고도 많은 곳에 적용할 수 있다.
Example Code : std 예제
#include <array>
#include <numeric>
int main()
{
constexpr std::array<int, 5> n{ 1,3,5,7,9 };
int d = std::accumulate(n.begin(), n.end(), 0);
}

array를 만들고 전체합을 계산했는데 예상과는 다르게 컴파일 시간에 계산하고 있지 않다.그 이유는 std::accumulate 함수의 constexpr 지원이 C++20부터 제공되기 때문이다.

std 버전을 C++ 20로 바꾸었더니 컴파일 시간에 계산되었다.
Example Code : Class 예제
class Square
{
public:
constexpr Square(int l) : mL(l) {}
constexpr int area() const { return mL*mL; }
constexpr int perimeter() const { return 4*mL; }
private:
int mL;
};
int main()
{
constexpr Square c{10};
int a = c.area();
int b = c.perimeter();
}

함수 호출 없이 계산된 결과값이 각 변수에 찍힌 것을 확인할 수 있다. constexpr을 활용하면 실행시간에 계산해야 할 연산들을 컴파일 시간으로 당겨오기 때문에 훨씬 최적화된 코드를 짤 수 있다. 하지만 계산에 들어갈 입력 값을 컴파일 시간에 미리 알고있어야하기 때문에 꽤나 제한적이다.
참고 출처 : Youtube 코드없는 프로그래밍
'C++ > Modern C++' 카테고리의 다른 글
[C++] attributes(속성) (0) | 2022.10.13 |
---|---|
[C++] Perfect forwarding (0) | 2022.10.05 |
스마트 포인터 문제 - 순환 참조 (0) | 2022.10.03 |
[C++20] std::span (0) | 2022.10.01 |
[C++] 문자열 정리 (0) | 2022.09.29 |