Namespaces
Variants

std::variant<Types...>:: variant

From cppreference.net
Utilities library
constexpr variant ( ) noexcept ( /* 아래 참조 */ ) ;
(1) (C++17부터)
constexpr variant ( const variant & other ) ;
(2) (C++17부터)
constexpr variant ( variant && other ) noexcept ( /* 아래 참조 */ ) ;
(3) (C++17부터)
template < class T >
constexpr variant ( T && t ) noexcept ( /* 아래 참조 */ ) ;
(4) (C++17부터)
template < class T,

class ... Args >
constexpr explicit variant ( std:: in_place_type_t < T > ,

Args && ... args ) ;
(5) (C++17부터)
template < class T,

class U,
class ... Args >
constexpr explicit variant ( std:: in_place_type_t < T > ,
std:: initializer_list < U > il,

Args && ... args ) ;
(6) (C++17부터)
template < std:: size_t I,

class ... Args >
constexpr explicit variant ( std:: in_place_index_t < I > ,

Args && ... args ) ;
(7) (C++17부터)
template < std:: size_t I,

class U,
class ... Args >
constexpr explicit variant ( std:: in_place_index_t < I > ,
std:: initializer_list < U > il,

Args && ... args ) ;
(8) (C++17부터)

새로운 variant 객체를 생성합니다.

1) 기본 생성자. 첫 번째 대안 타입의 값 초기화 된 값을 보유하는 variant 를 생성합니다 ( index() 는 0입니다).
  • 이 생성자는 대안 타입 T_0 의 값 초기화가 constexpr 함수 의 요구 사항을 충족하는 경우에만 constexpr 입니다.
  • 이 오버로드는 std:: is_default_constructible_v < T_0 > true 인 경우에만 오버로드 해결에 참여합니다.
2) 복사 생성자. other valueless_by_exception 이 아닌 경우, other 와 동일한 대안을 보유하는 variant 를 생성하고 포함된 값을 * std:: get_if < other. index ( ) > ( std:: addressof ( other ) ) 직접 초기화 합니다. 그렇지 않은 경우 valueless_by_exception variant를 초기화합니다.
3) 이동 생성자. 만약 other valueless_by_exception 이 아니라면, other 와 동일한 alternative를 보유하는 variant 를 생성하고 포함된 값을 std :: move ( * std:: get_if < other. index ( ) > ( std:: addressof ( other ) ) ) 직접 초기화 합니다. 그렇지 않으면 valueless_by_exception variant를 초기화합니다.
4) 변환 생성자. variant T_j 대안 타입을 보유하도록 생성하며, 이 타입은 F ( std:: forward < T > ( t ) ) 표현식에 대해 오버로드 해결이 수행될 때 선택될 타입입니다. 단, Types... 에 있는 각 T_i 에 대해 가상 함수 F(T_i) 의 오버로드가 존재한다고 가정하며, 축소 변환은 고려되지 않습니다.

형식적으로:

  • 오버로드 F ( T_i ) 는 선언 T_i x [ ] = { std:: forward < T > ( t ) } ; 가 어떤 고안된 변수 x 에 대해 유효할 때만 고려됩니다.
직접 초기화 로 포함된 값을 마치 std:: forward < T > ( t ) 로부터 직접 비목록 초기화하는 것처럼 초기화합니다.
  • 이 오버로드는 다음 조건을 모두 만족할 때만 오버로드 해결에 참여합니다:
  • 이 생성자는 T_j 의 선택된 생성자가 constexpr 생성자일 경우 constexpr 생성자입니다.
std::variant<std::string> v("abc"); // OK
std::variant<std::string, std::string> w("abc"); // 잘못된 형식
std::variant<std::string, const char*> x("abc"); // OK, const char* 선택
std::variant<std::string, bool> y("abc"); // OK, string 선택; bool은 후보가 아님
std::variant<float, long, double> z = 0; // OK, long 보유
                                         // float와 double은 후보가 아님
5) 지정된 alternative variant 를 구성하고 포함된 값을 인자들 std:: forward < Args > ( args ) ... 로 초기화합니다.
  • 만약 T 의 선택된 생성자가 constexpr 생성자라면, 이 생성자 또한 constexpr 생성자입니다.
  • 이 오버로드는 Types... 에서 T 가 정확히 한 번만 나타나고, std:: is_constructible_v < T, Args... > true 인 경우에만 오버로드 해결에 참여합니다.
6) 지정된 대안 variant 을 구성하고 포함된 값을 인수 il, std:: forward < Args > ( args ) ... 로 초기화합니다.
  • T 의 선택된 생성자가 constexpr 생성자인 경우, 이 생성자도 constexpr 생성자입니다.
  • 이 오버로드는 Types... 에서 T 가 정확히 한 번만 나타나고, std:: is_constructible_v < T, initializer_list < U > & , Args... > true 인 경우에만 오버로드 해결에 참여합니다.
7) 인덱스 I 로 지정된 T_i 대안을 가진 variant 를 구성하고 포함된 값을 인수 std:: forward < Args > ( args ) ... 로 초기화합니다.
  • 만약 T_i 의 선택된 생성자가 constexpr 생성자라면, 이 생성자 또한 constexpr 생성자입니다.
  • 이 오버로드는 I < sizeof... ( Types ) 이고 std:: is_constructible_v < T_i, Args... > true 인 경우에만 오버로드 해결에 참여합니다.
8) 인덱스 I 로 지정된 T_i 대안을 가진 variant 를 구성하고 포함된 값을 인수 il, std:: forward < Args > ( args ) ... 로 초기화합니다.
  • 만약 T_i 의 선택된 생성자가 constexpr 생성자라면, 이 생성자 또한 constexpr 생성자입니다.
  • 이 오버로드는 I < sizeof... ( Types ) 이고 std:: is_constructible_v < T_i, std:: initializer_list < U > & , Args... > true 인 경우에만 오버로드 해결에 참여합니다.

목차

매개변수

other - 복사/이동할 값을 포함하는 다른 variant 객체
t - 포함된 값을 초기화하는 데 사용할 값
args... - 포함된 값을 초기화하는 데 사용할 인수들
il - 포함된 값을 초기화하는 데 사용할 초기화 리스트

예외

1) 첫 번째 대안의 값 초기화에 의해 발생하는 모든 예외를 던질 수 있습니다.
2) Types... 내의 임의의 T_i 를 직접 초기화(direct-initializing)하는 과정에서 발생하는 모든 예외를 throw할 수 있습니다.
3) T_i 의 이동 생성 시 발생할 수 있는 모든 예외를 throw할 수 있습니다 Types... .
noexcept 명세:
noexcept ( ( std:: is_nothrow_move_constructible_v < Types > && ... ) )
4) 선택된 대안 T_j 의 초기화 과정에서 발생할 수 있는 모든 예외를 던질 수 있습니다.
noexcept 명세:
noexcept ( std:: is_nothrow_constructible_v < T_j, T > )
5-8) 선택된 대안의 선택된 생성자를 호출할 때 발생하는 모든 예외를 던질 수 있습니다.

참고 사항

MSVC STL은 초기에 P0608R3 을 C++20의 변경 사항으로 간주했습니다. VS 2022 17.12부터 MSVC STL은 P0608R3을 C++17에 대한 결함 보고서로도 취급합니다.

예제

#include <cassert>
#include <iostream>
#include <string>
#include <variant>
#include <vector>
using vector_t = std::vector<int>;
auto& operator<<(auto& out, const vector_t& v)
{
    out << "{ ";
    for (int e : v)
        out << e << ' ';
    return out << '}';
}
int main()
{
    // 첫 번째 대안을 값 초기화합니다
    std::variant<int, std::string> var0;
    assert(std::holds_alternative<int>(var0) and
           var0.index() == 0 and
           std::get<int>(var0) == 0);
    // 첫 번째 대안을 std::string{"STR"};로 초기화합니다.
    std::variant<std::string, int> var1{"STR"};
    assert(var1.index() == 0);
    std::cout << "1) " << std::get<std::string>(var1) << '\n';
    // int == 42로 두 번째 대안을 초기화합니다;
    std::variant<std::string, int> var2{42};
    assert(std::holds_alternative<int>(var2));
    std::cout << "2) " << std::get<int>(var2) << '\n';
    // 첫 번째 대안을 std::string{4, 'A'}로 초기화합니다;
    std::variant<std::string, vector_t, float> var3
    {
        std::in_place_type<std::string>, 4, 'A'
    };
    assert(var3.index() == 0);
    std::cout << "3) " << std::get<std::string>(var3) << '\n';
    // 두 번째 대안을 std::vector{1,2,3,4,5}로 초기화합니다;
    std::variant<std::string, vector_t, char> var4
    {
        std::in_place_type<vector_t>, {1, 2, 3, 4, 5}
    };
    assert(var4.index() == 1);
    std::cout << "4) " << std::get<vector_t>(var4) << '\n';
    // std::string{"ABCDE", 3}로 첫 번째 대안을 초기화합니다;
    std::variant<std::string, vector_t, bool> var5 {std::in_place_index<0>, "ABCDE", 3};
    assert(var5.index() == 0);
    std::cout << "5) " << std::get<std::string>(var5) << '\n';
    // 두 번째 대안을 std::vector(4, 42)로 초기화합니다;
    std::variant<std::string, vector_t, char> var6 {std::in_place_index<1>, 4, 42};
    assert(std::holds_alternative<vector_t>(var6));
    std::cout << "6) " << std::get<vector_t>(var6) << '\n';
}

출력:

1) STR
2) 42
3) AAAA
4) { 1 2 3 4 5 }
5) ABC
6) { 42 42 42 42 }

결함 보고서

다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.

DR 적용 대상 게시된 동작 올바른 동작
LWG 2901 C++17 할당자 인식 생성자가 제공되었지만
variant 가 할당자를 제대로 지원할 수 없음
생성자 제거됨
P0739R0 C++17 변환 생성자 템플릿이 클래스 템플릿 인수 추론과
부적절하게 상호작용함
제약 조건 추가됨
LWG 3024 C++17 멤버 타입 중 복사 불가능한 타입이 있으면
복사 생성자가 오버로드 해결에 참여하지 않음
대신 삭제된 것으로 정의됨
P0602R4 C++17 기본 생성자들이 trivial해도 복사/이동 생성자가
trivial하지 않을 수 있음
triviality 전파 요구됨
P0608R3 C++17 변환 생성자가 오버로드 집합을 무분별하게 구성하여
의도하지 않은 변환이 발생함
축소 변환과 bool 변환을 고려하지 않음
P1957R2 C++17 bool 에 대한 변환 생성자가
암시적 변환을 허용하지 않음
bool 에 대한 포인터 변환은 축소 변환이며
변환 생성자에 bool 에 대한
예외가 없음