<constexpr>
constexpr는 c++11 에서 추가된 키워드로서 컴파일 타임에 상수의 초깃값을 알 수있게 해주는 키워드 입니다. 일단 const 부터 확인하겠습니다.
| #include <iostream> using namespace std; int value(const int _x) { // 들어오는 인자를 상수로 받음 return _x; } int main() { int a; // 변수 cin >> a; const int b = a; // a를 통해 상수값 b를 만듬 b = 3; // b는 상수기 때문에 바뀔 수 없음 value(a); } | cs |
위와 같이 사용자 입력이나 또는 인자로 들어오는 상수값은 그때마다 변하기 때문에 런타임 시간내에서만 파악이 가능하고, 이를 런타임 상수라고 합니다. 위의 예제에서 b와 value(const int _x) 의 _x는 런타임 상수입니다.
다음은 constexpr 입니다.
| int main() { constexpr double a = 1.0; //ok, a는 컴파일 시간에 double 1.0 으로 치환됩니다. constexpr int b = 2; // ok, b는 컴파일 시간에 int 2 로 치환됩니다. int c; cin >> c; constexpr int d = c; //error, c는 런타임 변수입니다. 어떤 값이 들어올지 모르니 만들 수 없어요. constexpr int f; //error, 상수는 선언과 동시에 초기화 해줘야 합니다. } | cs |
const 와 constexpr의 차이점은 const 변수는 런타임까지 지연시켜 초기화가 가능하지만, constexpr 변수는 컴파일 타임에 초기화시켜야 한다는 것입니다. 컴파일 타임에 상수를 사용한다면, 조금 더 빠르고 적은 메모리로 사용할 수 있으며 배열 및 template의 인자로 사용할 수 있습니다. (template은 컴파일 타임에 실행되기 때문에)
| int arrayvalue(int _x) { return _x * 2; } constexpr int arrayvalue2(int _x) { return _x * 2; } int main() { const int i = 10; int myarray[arrayvalue(i)]; //error, 런타임내에 작동했으므로 배열값을 정할 수 없어요 int myarray2[arrayvalue2(i)]; //ok, 컴파일타임 내에 값을 유추했으므로 배열값으로 사용 가능 std::array<int, arrayvalue(i)> starray1; //error, 위와 같은 이유 std::array<int, arrayvalue2(i)> starray2; //ok, 위와 같은 이유 } | cs |
어떤 값의 2배를 arraysize로 사용하는 함수를 하나 만든다면, 이렇게 사용할 수 있는데 일반적인 arrayvalue 함수는 런타임시간내에 동작하기 때문에
컴파일시간내에 작동하는 배열 혹은 template의 인자로 사용될 수 없습니다.
<constexpr의 규칙>
constexpr 함수는 리터럴 형식만을 허용하거나 반환해야 합니다. constexpr 함수는 재귀적일 수 있습니다. 가상이 될 수 없습니다. 바깥의 크래스가 가상 기본 클래스를 가지고 있다면 생성자를 constexpr로 정의할 수 없습니다. ( virtual 사용 불가 ) 본문은 = default 또는 = delete 로 정의할 수 있습니다. 본문에는 goto 문이나 try 블록이 포함될 수 없습니다. constexpr이 아닌 템플릿의 명시적 특수화를 constexpr로 선언할 수 있습니다. constexpr 템플릿의 명시적 특수화도 constexpr일 필요는 없습니다.
다음 규칙이 Visual Studio 2017 이상의 constexpr 함수에 적용됩니다. if 및 switch 문을 포함할 수 있으며 for, 범위 기반 for, while, do-while을 포함한 모든 반복문을 포함할 수 있습니다. 지역 변수 선언을 포함할 수 있지만 변수는 초기화되어야 하고 리터럴 형식이여야 하며 정적 또는 쓰레드 로컬일 수 없습니다. 로컬로 선언된 변수는 const일 필요가 없으며 변경할 수 있습니다. Constexpr 비정적 멤버 함수는 암시적으로 const될 필요가 없습니다.
인용 : https://docs.microsoft.com/ko-kr/cpp/cpp/constexpr-cpp?view=vs-2017 |
<강한 열거형 (strongly-typed enum class)>
열거형은 정수 상수 집합으로 정의된 열거자의 집합입니다.
| enum A : int; //스코프가 없는 열거형을 만듭니다. 타입은 int enum class B; //스코프가 있는 열거형을 만듭니다. 타입은 int로 기본 enum class C : short; //스코프가 있는 열거형을 만듭니다. 타입은 short | cs
|
스코프가 있는 열거형은 enum class 이며 꼭, 스코프 연산자를 통해 접근해야 합니다.
1번의 enum A : int 는 enum A 와 같습니다.
| enum A : int { E_A_A = 1, E_A_B = 2, E_A_C = 3 }; enum class B { E_B_A = 1, E_B_B = 2, E_B_C = 3 }; int main() { A enumA = E_A_A; //ok, E_A_A 로 저장합니다. B enumB = E_B_A; //error, E_B_A는 어디에도 없습니다. B enumC = B::E_B_A; //ok, B 열거형 안에 있는 E_B_A 로 저장합니다. } | cs |
열거형은 캐스팅을 통한 변환도 가능합니다.
| enum A : int { E_A_A = 1, E_A_B = 2, E_A_C = 3 }; enum class B { E_B_A = 1, E_B_B = 2, E_B_C = 3 }; int main() { A enumA = static_cast<A>(1); //ok, enumA 는 A 열거형의 E_A_A 값입니다. B enumB = static_cast<B>(2); //ok, enumB 는 B 열거형의 E_B_A 값입니다. int temp = 100000; B enumC = static_cast<B>(temp); //ok, 그러나 B엔 100000과 매칭되는 값이 없습니다. 아마 버그가 날겁니다. } | cs |
다음은 사용자 정의 타입에 대한 내용인 explicit 와 = delete , = default , override 에 대해 작성하겠습니다. |