std::variant는 C++17에서 추가된 표준 라이브러리 클래스로, 여러 타입 중 하나를 저장할 수 있는 유연한 클래스입니다.
이전에는 유사한 기능을 하는 std::any를 사용해왔으나, std::variant는 더욱 타입 안전하고 간결하게 사용할 수 있습니다.
std::variant는 일반적으로 union과 비슷한 방식으로 작동합니다. 즉, 저장된 값은 선택한 타입의 크기와 정렬 요구 사항을 따릅니다.
std::variant는 다음과 같은 특징을 갖습니다.
- 여러 타입 중 하나를 저장할 수 있는 유연한 클래스
- 저장된 값은 선택한 타입의 크기와 정렬 요구 사항을 따름
- 선언할 때 모든 가능한 타입을 정의해야 하며, 선언 후에는 해당 타입들 중 하나의 값만 저장할 수 있음
- switch문과 함께 사용할 수 있는 visit 함수를 제공하여, 저장된 값의 타입에 따라 다른 작업을 수행할 수 있음
- 참조, 배열 또는 void 타입은 보유할 수 없음
- 동일한 타입을 한 번 이상 보유하고, 동일한 타입의 다르게 cv-qualified 된 버전을 보유할 수 있음
std::variant는 다음과 같이 선언할 수 있습니다.
std::variant<int, double, std::string> v;
위 코드는 int, double, std::string 중 하나를 저장할 수 있는 std::variant를 선언하는 것입니다.
선언 후에는 v에 int, double, std::string 중 하나의 값을 저장할 수 있습니다.
std::variant의 값을 가져오기 위해서는 std::get 함수를 사용할 수 있습니다.
std::variant<int, double, std::string> v;
v = 42;
int i = std::get<int>(v); // v에 저장된 int 값을 가져옴
위 코드는 v에 int 값 42를 저장하고, std::get<int>(v)를 사용하여 v에 저장된 int 값을 가져오는 것입니다.
std::variant를 switch문과 함께 사용하려면, visit 함수를 사용할 수 있습니다.
visit 함수는 각 타입에 대해 작업을 수행하는 함수 객체를 인수로 받습니다.
std::variant<int, double, std::string> v;
v = 3.14;
std::visit([](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int>) {
std::cout << "v contains an int: " << arg << '\n';
} else if constexpr (std::is_same_v<T, double>) {
std::cout << "v contains a double: " << arg << '\n';
} else if constexpr (std::is_same_v<T, std::string>) {
std::cout << "v contains a string: " << arg << '\n';
}
}, v);
위 코드는 v에 double 값 3.14를 저장하고, visit 함수를 사용하여 v에 저장된 값의 타입에 따라 다른 작업을 수행하는 것입니다.
다음은 서로 다른 타입의 메시지를 큐에 입력받는 샘플 코드입니다.
#include <queue>
#include <variant>
#include <string>
#include <iostream>
struct MessageA {
int type;
double data;
};
struct MessageB {
int type;
char data[20];
};
struct MessageC {
int type;
std::string data;
};
using Message = std::variant<MessageA, MessageB, MessageC>;
int main() {
std::queue<Message> messageQueue;
messageQueue.push(MessageA{1, 3.14});
messageQueue.push(MessageB{2, "hello world"});
messageQueue.push(MessageC{3, "foo bar"});
while (!messageQueue.empty()) {
const auto& message = messageQueue.front();
std::visit([](const auto& msg) {
using MsgType = std::decay_t<decltype(msg)>;
if constexpr (std::is_same_v<MsgType, MessageA>) {
std::cout << "MessageA received with data: " << msg.data << std::endl;
} else if constexpr (std::is_same_v<MsgType, MessageB>) {
std::cout << "MessageB received with data: " << msg.data << std::endl;
} else if constexpr (std::is_same_v<MsgType, MessageC>) {
std::cout << "MessageC received with data: " << msg.data << std::endl;
}
}, message);
messageQueue.pop();
}
return 0;
}
'C++' 카테고리의 다른 글
클래스 멤버 함수 포인터 (0) | 2023.02.15 |
---|---|
함수 포인터 (0) | 2023.02.14 |