C++20 리서치 - Designated Initialization, Constexpr, Consteval, etc..[5]
다음의 C++20에 추가된 기능을 살펴보겠습니다.
- Designated Initialization(지정된 초기화)
- Constexpr
- Consteval
- ETC…
Designated Initialization 지정된 초기화
Aggregate 초기화를 사용 할 때 명시적으로 멤버의 이름을 지정하여 초기화 하는 것
class Point3
{
int x, y, z;
}
int main()
{
//C++17
Point p0 = {1, 2, 3};
//C++20
Point p1 = {.x = 1, .y = 2, .z = 3};
Point p2 = {.x = 1, .z = 3}; // y는 0으로 초기화 됨
//C++20 부터는 클래스의 생성자가 없어도 하단 문법이 정상 처리됨
Point p3(1, 2, 3);
Point p4(1); //1, 0, 0
//주의 사항
Point p5 = {.y = 2, .x = 1}; // C++20에서 지정된 초기화의 멤버 순서가 바뀔 경우 오류 발생
Point p6 = {.x = 1, 2}; // 섞어서 쓸 경우 오류 발생
}
Constexpr 관련 변경점
- std::is_constant_evaluated() 함수 추가 : 어떤 함수가 컴파일 타임에 실행 되는지 여부
- constexpr virtual function : 가상 함수도 constexpr 사용 가능 (17 이전에는 불가능)
- std 알고리즘에 constexpr 지원
//constexpr : 컴파일 시간 또는 실행시간에 수행 될 수 있다
#include <algoritm>
#include <numeric>
#include <array>
constexpr auto add(int x, int y)
{
bool isCompileTime = std::is_constant_evaluated();
return std::pair(x+y, isCompileTime);
}
int main()
{
//is_constant_evaluated 관련
constexpr auto a = add(1, 2); // true
auto b = add(1, 2); // false;
int x = 1, y = 2;
auto c = add(x, y); // false
constexpr auto d = add(x, y); // 컴파일 에러 : 해당 표현은 컴파일 타임에 실행 될 수 없기에 constexpr를 제거해야 한다.
// std 알고리즘 관련 변화
constexpr int x[3] = {1, 2, 3};
//하단 std 컨테이너들도 constexpr 형으로 20 표준에서 지원 예정에 있다고 한다. 현재(2021-1-6)까지 아직 오류 발생
//constexpr std::array<int, 3> x = {1, 2, 3};
//constexpr std::vector<int, 3> x = {1, 2, 3};
constexpr int aa = std::accumulate(std::begin(x), std::end(x), 0); // std 알고리즘이 컴파일 타임에 계산되어 성능 최적화가 가능
constexpr auto gotIt = std::find(std::begin(x), std::end(x), 3); // std 알고리즘이 컴파일 타임에 계산되어 성능 최적화가 가능
}
신규 키워드 consteval
함수가 반드시 컴파일 시간에만 수행 될 수 있음을 명시(immediate function)
consteval int Add(int a, int b) { return a + b; }
int main()
{
int x = 1, y = 3;
int a = add(x, y); // 컴파일 에러
int b = add(1, 2); // 성공
}
C++20 추가된 간단한 문법들
-
explicit(bool) explicit 키워드를 사용시 적용 여부를 지정 할 수 있다.
//explicit 의미 : 복사 생성자 사용 불가, 생성자를 사용한 암시적 변환 불가 template<typename T> class Hello { T data; public: explicit( std::is_integral_v<T> ) Hello(T v) : data(v) // 정수형 일 때만 explicit가 적용되도록 구현 가능 }
-
ranged-for with initializer range for에 초기화 구문 표현이 가능
// 다음과 같은 표현이 가능해짐 C++20 for( int y[3]{1,2,3}; auto n : y) { } while ( int n = 0; n < 10) // while은 문법 오류 { }
-
using enum enum class 사용시 namespace 없이 사용 가능해짐
enum class Color { red = 1, green = 2, blue = 3 }; int main() { Color temp = color::red; switch(temp) { //case color::red: return 1; //case color::green: return 2; //다음과 같이 사용 할 경우 namespace 생략 가능해짐 using enum Color; case red: return 1; case green: return 2; } }