std::variant<Types...>:: variant
|
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
>
|
(5) | (C++17부터) |
|
template
<
class
T,
class
U,
|
(6) | (C++17부터) |
|
template
<
std::
size_t
I,
class
...
Args
>
|
(7) | (C++17부터) |
|
template
<
std::
size_t
I,
class
U,
|
(8) | (C++17부터) |
새로운
variant
객체를 생성합니다.
variant
를 생성합니다 (
index()
는 0입니다).
-
이 생성자는 대안 타입
T_0의 값 초기화가 constexpr 함수 의 요구 사항을 충족하는 경우에만 constexpr 입니다. - 이 오버로드는 std:: is_default_constructible_v < T_0 > 가 true 인 경우에만 오버로드 해결에 참여합니다.
variant
를 생성하고 포함된 값을
*
std::
get_if
<
other.
index
(
)
>
(
std::
addressof
(
other
)
)
로
직접 초기화
합니다. 그렇지 않은 경우
valueless_by_exception
variant를 초기화합니다.
-
이 생성자는
std::
is_copy_constructible_v
<
T_i
>
가
Types...
에 있는 모든
T_i에 대해 true 인 경우가 아니면 삭제된 것으로 정의됩니다. -
이 생성자는
std::
is_trivially_copy_constructible_v
<
T_i
>
가
Types...
에 있는 모든
T_i에 대해 true 인 경우 trivial합니다.
variant
를 생성하고 포함된 값을
std
::
move
(
*
std::
get_if
<
other.
index
(
)
>
(
std::
addressof
(
other
)
)
)
로
직접 초기화
합니다. 그렇지 않으면
valueless_by_exception
variant를 초기화합니다.
- 이 오버로드는 std:: is_move_constructible_v < T_i > 가 true 인 경우에만 오버로드 해결에 참여합니다.
-
모든
T_i에 대해 std:: is_trivially_move_constructible_v < T_i > 가 true 이면 trivial합니다.
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에 대해 유효할 때만 고려됩니다.
-
오버로드
F
(
T_i
)
는 선언
T_i x
[
]
=
{
std::
forward
<
T
>
(
t
)
}
;
가 어떤 고안된 변수
-
이 오버로드는 다음 조건을 모두 만족할 때만 오버로드 해결에 참여합니다:
- sizeof... ( Types ) > 0 ,
-
std::
decay_t
<
T
>
(C++20 이전)
std::
remove_cvref_t
<
T
>
(C++20 이후)
가
variant와 동일한 타입이 아니고, std::in_place_type_t 의 특수화도 아니며, std::in_place_index_t 의 특수화도 아닐 때, - std:: is_constructible_v < T_j, T > 가 true 일 때,
- 그리고 표현식 F ( std:: forward < T > ( t ) ) (F는 앞서 언급된 가상 함수들의 집합)이 올바르게 형성될 때.
-
이 생성자는
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은 후보가 아님
variant
를 구성하고 포함된 값을 인자들
std::
forward
<
Args
>
(
args
)
...
로 초기화합니다.
-
만약
T의 선택된 생성자가 constexpr 생성자라면, 이 생성자 또한 constexpr 생성자입니다. -
이 오버로드는
Types...
에서
T가 정확히 한 번만 나타나고, std:: is_constructible_v < T, Args... > 가 true 인 경우에만 오버로드 해결에 참여합니다.
variant
을 구성하고 포함된 값을 인수
il,
std::
forward
<
Args
>
(
args
)
...
로 초기화합니다.
-
T의 선택된 생성자가 constexpr 생성자인 경우, 이 생성자도 constexpr 생성자입니다. -
이 오버로드는
Types...
에서
T가 정확히 한 번만 나타나고, std:: is_constructible_v < T, initializer_list < U > & , Args... > 가 true 인 경우에만 오버로드 해결에 참여합니다.
I
로 지정된
T_i
대안을 가진
variant
를 구성하고 포함된 값을 인수
std::
forward
<
Args
>
(
args
)
...
로 초기화합니다.
-
만약
T_i의 선택된 생성자가 constexpr 생성자라면, 이 생성자 또한 constexpr 생성자입니다. - 이 오버로드는 I < sizeof... ( Types ) 이고 std:: is_constructible_v < T_i, Args... > 가 true 인 경우에만 오버로드 해결에 참여합니다.
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 | - | 포함된 값을 초기화하는 데 사용할 초기화 리스트 |
예외
T_i
를 직접 초기화(direct-initializing)하는 과정에서 발생하는 모든 예외를 throw할 수 있습니다.
T_i
의 이동 생성 시 발생할 수 있는 모든 예외를 throw할 수 있습니다
Types...
.
T_j
의 초기화 과정에서 발생할 수 있는 모든 예외를 던질 수 있습니다.
참고 사항
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 에 대한 예외가 없음 |