-
boost::variant(std::variant c++17) 사용하기프로그래밍/c++ 2016. 8. 5. 03:38반응형
boost::variant는 n개의 타입이 될 수 있는 타입이다.
boost::any와의 차이점은 지정된 형태로만 될 수 있으며 any와는 다르게 타입 변환 시 동적 할당을 사용하지 않기 때문에 퍼포먼스가 좀 더 뛰어나다.
boost::variant는 n개의 타입이 될 수 있는 타입이다. union의 c++판 업그레이드 버전 정도 되는 라이브러리라고 생각해도 괜찮다. 또, c++17에 표준으로 포함 되었으며 c++ 관련 커뮤니티에서의 반응도 긍정적이다. 일단 사용하는 방법이 깔끔하고 쉬우니까.
코드 >>
#include <boost/variant.hpp>
boost::variant<int, std::string, double> var;
// set
var = 0.01;
var = 123;
var = "hello";
// get
std::string s = boost::get<std::string>(var);
값을 얻을 땐 boost::get을 통해 얻어야 하며 잘못된 타입으로 get을 시도하면 런타임 예외가 발생한다.
코드 >>
#include <boost/variant.hpp>
boost::variant<int, std::string, double> var;
// set
var = 0.01;
var = 123;
var = "hello";
// get
std::string s = boost::get<std::string>(var);
boost::variant<double, std::string> var = 0.01;
try
{
std::string s = boost::get<std::string>(var); // 런타임 예외!
// std::vector v = boost::get<std::vector>(var); // 컴파일 타임 오류!
}
catch(const boost::bad_get& e)
{// 잘못된 variant 캐스트!
// ...
}
예외가 찜찜하다면, get에 variant 인스턴스의 포인터를 건네면 실패 시 nullptr을 주는 식으로 체크를 하는 것도 가능하다.
코드>>
boost::variant<double, std::string> var = "hello";
std::string* d = boost::get<double>(&var); // d는 nullptr이 된다.
std::string* s = boost::get<std::string>(&var); // s엔 정상적인 값이 들어간다.
방문자(Visitor)를 통한 연산을 지원하며, 이를 이용하면 사용자가 잘못된 get 캐스팅으로 인한 오류를 방지하고, 컨텐츠를 작성하는 부분을 좀 더 깔끔하게 만들 수도 있다. 주의 사항은 모든
코드>>
class cprint : public boost::static_visitor<>
{
public:
void operator()(const std::string& s) const
{
std::cout << s;
}
void operator()(const int& i) const
{
std::cout << i;
}
void operator()(const double& d) const
{
std::cout << d;
}
// or
// template < typename T >
// void operator()(const T& t) const
// {
// std::cout << t;
// }
};
// ..
boost::variant<int, double, std::string> var = "hello, hello";
boost::apply_visitor(cprint(), var); // 알맞는 게 출력된다.
마지막으로 for_each와 visitor를 이용해 지금의 것들을 응용해보자.
코드 >>
class cprint : public boost::static_visitor<>
{
public:
template < typename T >
void operator()(const T& t) const
{
std::cout << t;
}
};
// for_each
using var_t = boost::variant<int, double, std::string>;
std::vector<var_t> vars = {"hello", 1, 0.01};
std::for_each(vars.begin(), vars.end(), boost::apply_visitor(cprint())); // 모두 순회하며 콘솔에 출력한다.
반응형'프로그래밍 > c++' 카테고리의 다른 글
c++로 텍스트 파일 쓸 때 참고 (0) 2017.06.15 c++에서 람다를 함수 인자로 쓸 때 적절한 방법 (0) 2016.10.15 boost::any에서의 unsafe_any_cast (3) 2016.06.06 alignas, alignof 키워드 (0) 2016.05.07 c++11과 14의 brace-or-equal-initializer (0) 2016.05.03