Boost之Variant
来源:互联网 发布:土豆视频mac版下载 编辑:程序博客网 时间:2024/05/17 21:55
"The variant class template is a safe, generic, stack-based discriminated union container, offering a simple solution for manipulating an object from a heterogeneous set of types in a uniform manner. Whereas standard containers such as std::vector may be thought of as "multi-value, single type," variant is "multi-type, single value.
Problem
Many times, during the development of a C++ program, the programmer finds himself in need of manipulating several distinct types in a uniform manner. Indeed, C++ features direct language support for such types through its union keyword:
union { int i; double d; } u;
u.d = 3.14;
u.i = 3; // overwrites u.d (OK: u.d is a POD type)
C++'s union construct, however, is nearly useless in an object-oriented environment. The construct entered the language primarily as a means for preserving compatibility with C, which supports only POD (Plain Old Data) types, and so does not accept types exhibiting non-trivial construction or destruction:
union {
int i;
std::string s; // illegal: std::string is not a POD type!
} u;
union 的成员只能是POD类型。
//<boost程序完全开发指南>#include <boost/variant.hpp>#include <string>#include <iostream>using namespace boost;int main(){typedef variant<int, double, std::string> var_t;var_t v;assert(v.type() == typeid(int));assert(v.which() == 0);v = "variant demo";std::cout << *get<std::string>(&v) << std::endl; //使用get()函数取值try{std::cout << get<double>(v) << std::endl;}catch(bad_get &){std::cout << "bad_get" << std::endl;}std::cin.get();}
结果
variant demo
bad_get
const std::type_info& type() const;
返回type_info对象,可判别variant当前的数据类型
“我们也可以使用自由函数get()来获取variant的值:
cout << get<string>(v)”
“但get()函数通常不是最方便的访问方法,”它存在类型不安全的隐患,操作时必须查询variant当前值的类型。
改进版
//<me>#include <boost/variant.hpp>#include <string>#include <iostream>using namespace boost;typedef variant<int, double, std::string> var_t;void var_print(var_t & v){if(v.type() == typeid(int)){std::cout << get<int>(v) << std::endl;}else if(v.type() == typeid(double)){std::cout << get<double>(v) << std::endl;}else if(v.type() == typeid(std::string)){std::cout << get<std::string>(v) << std::endl;}else{std::cout << "error type" << std::endl;}}int main(){var_t v;v = "variant demo";var_print(v);v = 3.14;var_print(v);v = 909;var_print(v);std::cin.get();}
结果:
variant demo
3.14
909
函数var_print()将输入的variant对象输出,它使用了RTTI技术,效率低,并且一旦variant的模板参数发生变化,var_print()也必须改动,其if_else的处理结果也很不优雅。
Variant基于访问者模式提供了模板类static_visitor"
//<.修改代码>#include <boost/variant.hpp>#include <string>#include <iostream>using namespace boost;typedef variant<int, double, std::string> var_t;class print_visitor : public static_visitor<void> {public:void operator()(int i) const{std::cout << "It's an int: " << i << '\n';}void operator()(std::string s) const{std::cout << "It's a std::string: " << s << '\n';}void operator()(double d) const{std::cout << "It's a double: " << d << '\n';}};int main(){print_visitor v;var_t var;var = "variant demo";boost::apply_visitor(v, var);var = 3.14;boost::apply_visitor(v, var);var = 909;boost::apply_visitor(v, var);std::cin.get();}
结果:
It's a std::string: variant demo
It's a double: 3.14
It's an int: 909
二元访问器
“之前的访问器都只能操作一个variant对象,但操作两个variant对象的访问器也允许的,这在某些情况下是有用的,比如对两个variant进行比较。”
"注意,如果调用 get 失败(当 my_first_variant 所含值不是类型 int 时就会发生),会抛出一个类型为 boost::bad_get 的异常。"
- Boost之Variant
- boost学习之-Variant
- boost之variant使用
- boost之variant
- boost总结之variant
- Boost::Variant
- boost::variant
- C++学习 boost学习之-Variant
- C++boost库之variant使用
- C++boost库之variant使用
- Boost库之tuple、any和variant的使用
- BOOST中的union:boost::variant
- boost::variant and boost::apply_visitor
- boost::variant的简单介绍
- boost::any 与 boost::variant 的区别
- boost::any 与 boost::variant 的区别
- boost::tie()和boost::variant()讲解
- boost::tie()和boost::variant()讲解
- SQLite 3 一些基本使用
- {dede:list} [field:description] 限制长度
- 随机论---生命起源随想
- SQLite3
- 内核驱动中常见的miscdevice、platform_device、platform_driver
- Boost之Variant
- ArrayList、LinkedList、Set等介绍
- ibatis 读取CLOB数据
- Posix多线程编程学习笔记(一)—线程基础(1)
- Spring JDBC事务管理
- 通过修改电源管理驱动,实现WinCE5.0关机功能
- 时间函数
- 教你如何打开设了密码的电脑
- Linux - one command per day--ln