Namespaces
Variants

std:: variant

From cppreference.net
Utilities library
헤더 파일에 정의됨 <variant>
template < class ... Types >
class variant ;
(C++17부터)

클래스 템플릿 std::variant 는 타입 안전 union 을 나타냅니다.

variant 의 인스턴스는 언제든지 대체 타입 중 하나의 값을 보유하거나, 오류 발생 시에는 값을 보유하지 않습니다(이 상태는 달성하기 어렵습니다. valueless_by_exception 참조).

union과 마찬가지로, variant가 객체 타입 T 의 값을 보유하는 경우, T 객체는 내부에 중첩되어 variant 객체 안에 위치합니다.

variant는 참조, 배열 또는 void 타입을 보유할 수 없습니다.

variant은 동일한 타입을 여러 번 보유하는 것이 허용되며, 동일한 타입의 서로 다른 cv 한정 버전을 보유할 수 있습니다.

aggregate initialization 동안의 union 동작과 일관되게, 기본 생성된 variant는 첫 번째 alternative의 값을 보유합니다. 단, 해당 alternative가 기본 생성 가능하지 않은 경우는 예외입니다(이 경우 variant도 기본 생성 가능하지 않습니다). 헬퍼 클래스 std::monostate 를 사용하면 이러한 variant를 기본 생성 가능하게 만들 수 있습니다.

템플릿 인수 없이 std::variant 의 정의를 인스턴스화하는 프로그램은 형식이 잘못되었습니다. std :: variant < std:: monostate > 를 대신 사용할 수 있습니다.

프로그램이 explicit 또는 partial specialization을 선언하는 경우, 그 프로그램은 진단 없이 잘못된 형식입니다.

목차

템플릿 매개변수

Types - 이 variant에 저장될 수 있는 타입들. 모든 타입은 Destructible 요구사항을 충족해야 합니다 (특히, 배열 타입과 비객체 타입은 허용되지 않습니다).

멤버 함수

variant 객체를 생성한다
(public member function)
variant 와 그 안에 포함된 값을 소멸시킨다
(public member function)
variant 에 값을 할당한다
(public member function)
Observers
variant 가 보유한 대안의 0 기반 인덱스를 반환한다
(public member function)
variant 가 무효 상태인지 확인한다
(public member function)
Modifiers
variant 내에 값을 제자리에서 생성한다
(public member function)
다른 variant 와 교환한다
(public member function)
Visitation
(C++26)
제공된 함수자를 variant 가 보유한 인수로 호출한다
(public member function)

비멤버 함수

(C++17)
하나 이상의 variant 가 보유한 인자들로 제공된 함수 객체를 호출합니다
(함수 템플릿)
variant 가 현재 주어진 타입을 보유하고 있는지 확인합니다
(함수 템플릿)
인덱스나 타입(타입이 고유한 경우)으로 variant의 값을 읽고, 오류 시 예외를 발생시킵니다
(함수 템플릿)
(C++17)
인덱스나 타입(고유한 경우)으로 가리키는 variant 의 값에 대한 포인터를 얻고, 오류 시 null을 반환합니다
(함수 템플릿)
(C++17) (C++17) (C++17) (C++17) (C++17) (C++17) (C++20)
variant 객체를 포함된 값들로 비교합니다
(함수 템플릿)
std::swap 알고리즘을 특수화합니다
(함수 템플릿)

헬퍼 클래스

(C++17)
기본 생성 불가능한 타입들의 variant 에서 첫 번째 대안으로 사용하기 위한 플레이스홀더 타입
(클래스)
variant 값에 대한 잘못된 접근 시 발생하는 예외
(클래스)
컴파일 타임에 variant 의 대안 목록 크기를 구함
(클래스 템플릿) (변수 템플릿)
컴파일 타임에 인덱스로 지정된 대안의 타입을 구함
(클래스 템플릿) (별칭 템플릿)
std::variant 에 대한 해시 지원
(클래스 템플릿 특수화)

헬퍼 객체

variant 이 유효하지 않은 상태일 때의 인덱스
(상수)

참고 사항

기능 테스트 매크로 표준 기능
__cpp_lib_variant 201606L (C++17) std::variant : 타입 안전한 유니온
202102L (C++23)
(DR17)
std::visit for classes derived from std::variant
202106L (C++23)
(DR20)
완전한 constexpr std::variant
202306L (C++26) 멤버 visit

예제

#include <cassert>
#include <iostream>
#include <string>
#include <variant>
int main()
{
    std::variant<int, float> v, w;
    v = 42; // v는 int를 포함
    int i = std::get<int>(v);
    assert(42 == i); // 성공
    w = std::get<int>(v);
    w = std::get<0>(v); // 이전 줄과 동일한 효과
    w = v; // 이전 줄과 동일한 효과
//  std::get<double>(v); // 오류: [int, float]에 double 없음
//  std::get<3>(v);      // 오류: 유효한 인덱스 값은 0과 1
    try
    {
        std::get<float>(w); // w는 float가 아닌 int를 포함: 예외 발생
    }
    catch (const std::bad_variant_access& ex)
    {
        std::cout << ex.what() << '\n';
    }
    using namespace std::literals;
    std::variant<std::string> x("abc");
    // 변환 생성자는 모호하지 않을 때 작동
    x = "def"; // 변환 할당도 모호하지 않을 때 작동
    std::variant<std::string, void const*> y("abc");
    // char const*가 전달될 때 void const*로 캐스트
    assert(std::holds_alternative<void const*>(y)); // 성공
    y = "xyz"s;
    assert(std::holds_alternative<std::string>(y)); // 성공
}

가능한 출력:

std::get: wrong index for variant

결함 보고서

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

DR 적용 대상 게시된 동작 올바른 동작
LWG 2901 C++17 std::uses_allocator 특수화가 제공되었으나,
variant 가 할당자를 제대로 지원할 수 없음
특수화 제거됨
LWG 3990 C++17 프로그램이 std::variant 의 명시적 또는
부분 특수화를 선언할 수 있었음
이 경우 프로그램의 형식이 잘못됨
(진단 메시지 필요 없음)
LWG 4141 C++17 저장소 할당 요구사항이
혼란스러웠음
포함된 객체는 variant 객체 내에
중첩되어야 함

참고 항목

인-플레이스 생성 태그
(태그)
(C++17)
객체를 보유할 수도 있고 보유하지 않을 수도 있는 래퍼
(클래스 템플릿)
(C++17)
모든 CopyConstructible 타입의 인스턴스를 보유하는 객체
(클래스)