반응형
any
std::any: How, when, and why | C++ Team Blog
임의의 사용자 데이터 저장하기
다른 개발자에게 달력 라이브러리를 배포한다고 생각해봅시다. 하루 일정은 한 주 일정에 포함되고, 다시 한 주 일정은 월 일정에 포함되어야 할 것입니다. 그리고 각 일정마다 일일 계획 또는 한 주 계획을 저장할 수 있도록 크기가 정해지지 않은 데이터 (user data)를 담을 수 있는 데이터 구조를 만들어야 합니다.
아마 C 개발자라면 임의의 데이터를 받기 위해 void 포인터를 이용할 것입니다.
struct day {
// ...
void* user_data;
};
struct month {
std::vector<day> days;
void* user_data;
};
some_day.user_data = new std::string("Hello, wirld!");
그러나 void 포인터를 이용하는 것에는 몇가지 중대한 문제가 있습니다.
- 먼저 void 포인터는 어느 객체의 포인터라도 가리킬 수 있습니다. 타입에 대한 정보가 없다는 것은 타입에 대한 안정성을 보장하지 못한다는 뜻입니다.
- 또 void 포인터는 스마트 포인터처럼 수명 관리를 할 수 없다는 점입니다.
std::any 사용하기
std::any는 똑똑한 void*/shared_ptr와 같습니다. 복사 가능한 타입이라면 어떤 값이든 초기화할 수 있습니다.
std::any a0;
sdt::any a1 = 10;
std::any a2 = month{"October");
std::any 멤버 변수
- emplace: 저장된 객체를 새로운 객체로 복사 없이 변경
- has_value: 객체가 값을 가지는 지 확인
- type: 객체가 가진 값의 typeid를 반환
#include <any>
#include <iostream>
int main()
{
std::cout << std::boolalpha;
// any type
std::any a = 1;
std::cout << a.type().name() << ": " << std::any_cast<int>(a) << '\n';
a = 3.14;
std::cout << a.type().name() << ": " << std::any_cast<double>(a) << '\n';
a = true;
std::cout << a.type().name() << ": " << std::any_cast<bool>(a) << '\n';
// bad cast
try
{
a = 1;
std::cout << std::any_cast<float>(a) << '\n';
}
catch (const std::bad_any_cast& e)
{
std::cout << e.what() << '\n';
}
// has value
a = 1;
if (a.has_value())
{
std::cout << a.type().name() << '\n';
}
// reset
a.reset();
if (!a.has_value())
{
std::cout << "no value\n";
}
// pointer to contained data
a = 1;
int* i = std::any_cast<int>(&a);
std::cout << *i << "\n";
}
반응형
'💻 programming > c++' 카테고리의 다른 글
[c++] template specialization (0) | 2020.12.15 |
---|---|
[c++] template (0) | 2020.12.15 |
[c++] optional (0) | 2020.12.15 |
[c++] move (0) | 2020.12.15 |
[c++] perfect forwarding (완벽한 전달) (0) | 2020.12.15 |
댓글