C++/STL

[C++17] std::variant

sseram 2023. 11. 12. 23:01
반응형

공식 문서는 아래.

 

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

 

std::variant - cppreference.com

template< class... Types > class variant; (since C++17) The class template std::variant represents a type-safe union. An instance of std::variant at any given time either holds a value of one of its alternative types, or in the case of error - no value (th

en.cppreference.com

 

 

쉽게 말하자면, 우리가 알고 있던 union 이라는 구조체를 standard library로 가져왔다고 보면 될 듯 하다.

 

 union 구조체 사용하듯 사용하면 되지만, 몇 가지 조건이 있다.

 

 

 

1. void type을 저장할 수 없다.

2. reference type을 저장할 수 없다.

3. array type을 저장할 수 없다.

 

1,2,3 예제

 

4. default constructor 가 없는 type만을 저장할 수 없다.

4 예제

> 다만 std::monostate를 사용하면 위에도 가능하게 만들 수 있다.

 

 

 


 

 

 

사용법은 일반 union 사용하는 것 처럼 사용할 수 있다.

 #include <cassert>
#include <iostream>
#include <string>
#include <variant>

int main()
{
    // 1. 기본적인 사용 예제
    std::variant<int, float> v;
    v = 42; 
    int i = std::get<int>(v);
    assert(42 == i); 
    
    
    // 2. 아래 w 로 대입하는 세 줄은 모두 같은 의미
    std::variant<int, float> w;
    w = std::get<int>(v);
    w = std::get<0>(v);
    w = v;
    
 

 
    // 3. 잘못 가져왔을 때의 exception
    //  std::get<double>(v); // error: no double in [int, float]
    //  std::get<3>(v);      // error: valid index values are 0 and 1
    try
    {
        std::get<float>(w); // w contains int, not float: will throw
    }
    catch (const std::bad_variant_access& ex)
    {
        std::cout << ex.what() << '\n';
    }
 
 
    // 4. 아래와 같은 문자열은 기본적으로 const char*로 처리.
    std::variant<std::string, void const*> y("abc");
    assert(std::holds_alternative<void const*>(y)); // y 는 void const* type 형태
    y = "xyz"s;	// string litetral 을 붙여서 string임을 명시.
    assert(std::holds_alternative<std::string>(y)); // y 는 string 형태
}

 

 

 

끝!

 

union.. 자주 안 쓰긴 하는데, 만약 쓸 일이 있다고 하면 union 대신 std::variant를 사용하도록 하자.

 

 

 

 

* 잘못된 정보는 알려주시면 감사한 마음으로 수정하겠습니다.

반응형