[C++] C++17 variant

언어/C++ 2018. 12. 30. 22:21

variant는 진화된 공용체다.


기존의 union은 문제가 많았다.


예를 들어 기존의 union을 쓸 때, 

double 버전으로 값을 넣고 int 버전으로 사용을 한다 해도 아무런 문제 없이 작동이 된다.


하지만 출력값을 보면 알겠지만 값이 정상적이지 않다.


C의 공용체는 아무런 타입 검사를 수행하지 않는다. 이 때문에 C의 공용체는 타입-safe하지 못하다고 한다.


아무튼 저런 맛이 간 출력값이 나온 이유는 아무런 조치 없이 메모리에 존재하는 비트값을 그대로 읽어왔기 때문이다. 정수 타입과 실수 타입의 메모리 구조는 완전히 다르다. 게다가 엔디언과 바이트 크기까지 고려하면 같은 계열의 타입이라도 괴리가 발생할 수가 있다.


물론 이런걸 이용해서 편법적으로 사용할 수도 있지만, 

실제로 이런 식의 접근은, 99% 사용자의 실수에서 발생한다. 그리고 실수는 결함으로 이어진다.

union은 이처럼 안전성에 문제가 많다.


게다가 기존의 union은 생성자/소멸자/가상메서드가 없는 이른바 POD 타입만을 멤버로 둘 수가 있다는 심각한 기능적 결함이 있었다.

다시말해 C++스타일의 타입은 제대로 담아둘수 없었다는 것이다.



C++17에서는 이런 문제들을 해결한 variant라는 멋진 녀석을 내놓았다.


variant는 타입-safe한 공용체 템플릿이다.

당연히 C++ 스타일의 클래스도 멤버로 둘 수 있다.


기존의 공용체와 다른 특징으로, 이녀석은 반드시 초기화를 해야만 접근 타입을 바꿀 수가 있다.

해당 타입으로의 초기화를 수행하지 않고 접근을 한다면 예외가 발생한다.

아마 이런 방식을 통해서 타입체킹도 엄격하게 하고 생성자/소멸자도 써먹을 수 있게 한 것 같다.



일단 아래 코드는 아주 정상적으로 작동하는 코드다.

int 타입으로 값 대입 한번 해주고, 접근해서 출력하고.

double로 초기화해주고, 접근해서 출력한다.




하지만 초기화를 수행하지 않으면 이렇게 예외가 나온다.

이렇게



그리고 애초에 없는 타입이나 인덱스는 당연히 컴파일부터가 안 된다.



암튼 그렇다.


자세한 건 레퍼런스를 참조

https://en.cppreference.com/w/cpp/utility/variant

'언어 > C++' 카테고리의 다른 글

[C++] R-Value Reference와 Move Semantic  (0) 2019.09.03
[C++] Q: 왜 동적배열이 vector가 된건가요?  (0) 2019.09.03
[C++] C++17 optional  (0) 2018.12.30

설정

트랙백

댓글