1.boost::any
boost::any是一种通用的数据类型,可以将各种类型包装后统一放入容器内
最重要的它是类型安全的有点象COM里面的variant.
使用方法:
any::type() 返回包装的类型
any_cast可用于any到其他类型的转化
void<boost::any>2string("test"for(unsigned int i=0;i<a.size();++<<a[i].type().name()<<tryint result = any_cast<int><<result<<catch(boost::bad_any_cast &<<"cast error:"<<ex.what()<<
2.boost::array
void<boost::any>2string("test"for(unsigned int i=0;i<a.size();++<<a[i].type().name()<<tryint result = any_cast<int><<result<<catch(boost::bad_any_cast &<<"cast error:"<<ex.what()<<
2.boost::array
boost::array仅仅是对数组一层薄薄的封装,提供跟各种算法配合的iterator,使用方法很简单
注意:可以使用{}来初始化array,因为array所有的成员变量都是public的
void<int,10> ai =for(size_t i=0;i<ai.size();++
3.boost::lexical_cast
lexical_cast用于将字符串转换成各种数字类型(int,float,short etc.)
void<int,10> ai =for(size_t i=0;i<ai.size();++
3.boost::lexical_cast
lexical_cast用于将字符串转换成各种数字类型(int,float,short etc.)
voidint i = boost::lexical_cast<int>("123"<< i <<
4.boost::format
boost::format是用于替代c里面的sprintf,优点是类型安全,不会因为类型和参数不匹配而导致程序崩溃了
而且还可以重复使用参数
voidint i = boost::lexical_cast<int>("123"<< i <<
4.boost::format
boost::format是用于替代c里面的sprintf,优点是类型安全,不会因为类型和参数不匹配而导致程序崩溃了
而且还可以重复使用参数
void<< boost::format("writing %1%, x=%2% : %3%-th try") %"toto"%40.23%50<<"a=%1%,b=%2%,c=%3%,a=%1%"%"string"%2%10.0<< f.str() <<
5.boost::tokenizer
boost::tokenizer是用于切割字符串的,类似于Java里面的StringTokenizer
void<< boost::format("writing %1%, x=%2% : %3%-th try") %"toto"%40.23%50<<"a=%1%,b=%2%,c=%3%,a=%1%"%"string"%2%10.0<< f.str() <<
5.boost::tokenizer
boost::tokenizer是用于切割字符串的,类似于Java里面的StringTokenizer
voidstring s("This is , a ,test!"<>for(tokenizer<>::iterator beg=tok.begin(); beg!=tok.end();++beg)
6.boost::thread
boost::thread是为了提供跨平台的thread机制利用boost::function来完成委托
void<<"hello,thread!"<<void<void () ><<"thread is over!"<<
7.boost::serialization
boost::serialization提供object的序列化功能而且提供好几种序列化的格式,比如text,binary,xml
void<<"hello,thread!"<<void<void () ><<"thread is over!"<<
7.boost::serialization
boost::serialization提供object的序列化功能而且提供好几种序列化的格式,比如text,binary,xml
void{
boost::archive::text_oarchive to(cout , boost::archive::no_header);
int i =10string s ="This is a test\n"&&"test.xml");
boost::archive::xml_oarchive xo(f);
xo & BOOST_SERIALIZATION_NVP(i) & BOOST_SERIALIZATION_NVP(s);
boost::archive::text_iarchive ti(cin , boost::archive::no_header);
ti & i &<<"i="<< i <<<<"s="<< s <<
8.boost::function
boost::function就是所谓的泛函数,能够对普通函数指针,成员函数指针,functor进行委托,达到迟调用的效果
int foo(int x,int<<"(foo invoking)x = "<<x <<" y = "<< y <<return x+structint foo(int x,int<<"(test::foo invoking)x = "<<x <<" y = "<< y <<return x+void<int (int,int)>=<<"f(2,3)="<<f(2,3)<</*f = std::bind1st(
std::mem_fun(&test::foo), &x);*/<int (test*,int,int)>=&<<"f2(5,3)="<<f2(&x,5,3)<<
9.boost::shared_ptr
boost::shared_ptr就是智能指针的实现,不象std::auto_ptr,它是可以stl的容器一起使用的,非常的方便
int foo(int x,int<<"(foo invoking)x = "<<x <<" y = "<< y <<return x+structint foo(int x,int<<"(test::foo invoking)x = "<<x <<" y = "<< y <<return x+void<int (int,int)>=<<"f(2,3)="<<f(2,3)<</*f = std::bind1st(
std::mem_fun(&test::foo), &x);*/<int (test*,int,int)>=&<<"f2(5,3)="<<f2(&x,5,3)<<
9.boost::shared_ptr
boost::shared_ptr就是智能指针的实现,不象std::auto_ptr,它是可以stl的容器一起使用的,非常的方便
classpublic<<"ctor() called"<<const Shared &<<"copy ctor() called"<<~<<"dtor() called"<<&operator= (const Shared &<<"operator = called"<<void<Shared><SharedSP> VShared;
VShared v;
v.push_back(SharedSP(newnew
xml解析可以用xml4c
socket最好用ACE,就是上手比较难
database一种是使用ADO,另一种是厂家提供的API
听说boost::socket开发很长时间了,可是没成型
boost::logging也还没出来
int
, 就无需保存一个版本号到存档中。同样的,对于不会通过指针来序列化的数据类型,也无需跟踪保存到存档或从存档取出的对象的地址,因为该对象无论如何不会被保存/取出一次以上。所以特定数据类型的序列化细节,依据类型、程序员的用法和规格而有所不同。
你可以通过指定一个或多个 类序列化traits 来改变特定数据类型的序列化方式。对于程序员来说,通常并不需要为他的类显式地指定 traits,因为所有的 traits 都有缺省值。如果缺省值不适用,程序员才需要对它赋值。可以用一个模板来把一个常量关联到一个类型名。相关例子请见 version.hpp.
版本
该头文件包含以下代码:
namespace boost {
namespace serialization {
template<class T>
struct version
{
BOOST_STATIC_CONSTANT(unsigned int, value = 0);
};
} // namespace serialization
} // namespace boost
对于任意类
T
,
boost::serialization::version<T>::value
的缺省定义是 0. 如果我们想将类
my_class
的版本赋为2,我们指定如下版本模板:
namespace boost {
namespace serialization {
struct version<my_class>
{
BOOST_STATIC_CONSTANT(unsigned int, value = 2);
};
} // namespace serialization
} // namespace boost
现在无论何时需要类
my_class
的版本号,都将返回2而不是缺省值0.
为了简化代码和增强可读性,系统定义了一个宏来替代以上写法,我们可以写:
BOOST_CLASS_VERSION(my_class, 2)
它将扩展为前述代码。
实现级别
采用和上述相同的风格,可以指定序列化实现的 "级别"。头文件 level.hpp 定义如下:
// 各个级别的名字
enum level_type
{
// 不要序列化本类型。尝试这样做将引起编译期断言。
not_serializable = 0,
// 直接将本类型写/读到存档。这样情形下不调用序列化代码。对于基本类型,这是缺省情况。
// 它假设存档类的一个成员函数或模板可以处理该类型。该级别实例的读/写没有运行期开销。
primitive_type = 1,
// 使用对象的"序列化"函数或模板对本类型的对象进行序列化。允许值被写/读到存档,但不
// 包含类信息和版本信息。
object_serializable = 2,
///
// 一个对象以上述级别之一进行序列化后,如果存档对象的实现级别被改变,相应的存档将不
// 不能读出。
///
// 增加类信息到存档中。类信息包含实现级别、类版本和类名。
object_class_info = 3,
};
使用
level.hpp
中提供的一个宏,我们可以指定
my_class
要和它的版本号一起序列化:
BOOST_CLASS_IMPLEMENTATION(my_class, boost::serialization::object_class_info)
如果没有显式指定实现级别,系统将按以下规则使用缺省值:
- 如果数据类型为
volatile
则采用not_serializable
- 否则,如果是枚举或基本类型,则采用
primitive_type
- 否则采用
object_class_info
object_serializable
来覆盖缺省的
object_class_info
,以换取更高的效率。 例如,对于
binary_object 包装
就是这样做的。
对象跟踪
依赖于类型被使用的方式,可能需要跟踪对象被保存和导入的地址。例如,如果是通过指针来进行对象序列化,就通常需要这样做,以确保在存档导入时不会创建多个相同的对象。这个 "跟踪行为" 是通过定义于头文件 tracking.hpp 中的类型 trait 来控制的,该头文件定义如下:
// 各个跟踪级别的名字
enum tracking_type
{
// 从不跟踪本类型
track_never = 0,
// 如果通过指针来序列化,则跟踪本类型的对象。
track_selectively = 1,
// 总是跟踪本类型
track_always = 2
};
系统定义了一个相应的宏,所以我们可以用:
BOOST_CLASS_TRACKING(my_class, boost::serialization::track_never)
缺省的跟踪 traits 是:
- 对于基本类型,
track_never
. - 对于指针,
track_never
. 即,地址的地址缺省不被跟踪。 - 对于所有现有的序列化包装,如
boost::serialization::nvp
,track_never
. - 对于所有其它类型,
track_selectivly
. 即,跟踪序列化对象的地址当且仅当以下一条或多条为真:- 在程序的某处,通过指针对该类型的对象进行序列化。
- 该类被显式地 "输出exported" - 见后
- 该类被显式地 "注册" 到存档
缺省的行为几乎总是最方便的。不过,有少数情形需要覆盖缺省的行为。一种情形是虚拟基类。在带有虚拟基类的菱形继承结构中,对象跟踪应防止多余的保存/导入。这种情形下可能就要覆盖缺省的跟踪 trait. (注意:在未来的版本中,缺省实现将自动跟踪被用作虚拟基类的类)。这种情形在本库的 test_diamond.cpp 中有相关示例。
输出键
当通过一个基类指针对派生类进行序列化时,要定义一个外部名字以便派生类可以被识别。 (在本手册的 其它音节,详细介绍了派生类的序列化) 标准 C++ 实现了typeid()
用于对一个类返回一个唯一的字符串。由于以下原因它并不能完全满足我们的目标:
- 它不能保证该字符串在跨平台环境下是一致的。这将无法支持可移植的存档。
- 在使用来自不同来源的代码模块时,类可能被包装在不同程序的不同名字空间中。
- 在不同代码模块中局部定义的类可能具有相同的名字。
- 有可能不同名字的类,但我们在执行序列化时将它们视为等价。
BOOST_CLASS_EXPORT_GUID(my_class, "my_class_external_identifier")
在大多数应用中,类名就是很好的外部标识字符串,所以系统定义了以下简写:
BOOST_CLASS_EXPORT(my_class)
它会扩展为:
BOOST_CLASS_EXPORT_GUID(my_class, "my_class")
如果在程序的某处需要一个外部名字而又未被指定,则将产生一个静态断言。
抽象
当通过基类指针序列化一个对象且该基类为抽象类(即至少有一个虚拟函数被赋为0)时,将产后一个编译错误。这可以通过下列中的一个或几个方法来解决:- 去掉基类中的 =0 以使该基类不再是抽象的。
- 为你的编译器实现 is_abstract. (本库的代码是依照C++标准编写的。但已知有几个编译器不能通过编译)
- 使用宏
BOOST_IS_ABSTRACT(my_class)
来表明该类为抽象基类。这将使编译器不会生成引起错误的代码。
类型信息的实现
最后这个 trait 也是与通过基类指针进行对象序列化有关。该功能的实现需要这样一种能力,即在运行时推断基类指针所指对象的真正类型。不同的序列化系统以不同方法来实现。在我们的系统中,缺省的方法是使用函数typeid(...)
,该函数在支持
RTTI
(
R
un
T
ime
T
ype
I
nformation)的系统中都是可用的。对于绝大多数情况,这已经够用了,所以本库的大多数用户就算跳过本节也不会有所损失。
不过,有些情形下缺省的类型推断系统会不太好用。有些平台可能不支持 RTTI 或者它因为执行速度或其它原因被禁用。有些应用,如需要在运行时链接插件模板的应用,就不能依赖于 C++ RTTI 来推断真实的派生类型。RTTI 只能返回多态类的正确类型 - 即至少有一个虚拟函数的类。如果以上情形中的一个出现,你可能就要用自己的实现来替代 extended_type_info
了。
实现序列化所要求的工具接口定义在 extended_type_info.hpp. 该工具的缺省实现基于 typeid(...)
,定义于 extended_type_info_typeid.hpp. 另一个实现基于外部的类标识,定义于 extended_type_info_no_rtti.hpp.
通过调用宏:
BOOST_CLASS_TYPE_INFO(
my_class,
extended_type_info_no_rtti<my_class>
)
我们可以按需要为每个类指定类型信息的实现方式。并不要求一个程序中的所有类要使用相同的
extended_type_info
实现。可以在头文件中指定类的序列化信息,然后在任何项目中包含该头文件而无需修改。
在测试程序 test_no_rtti.cpp 中有相关的说明。对于一些特定情形,也可能需要有其它的实现方法。
模板的序列化 Traits
有时候,可能需要一次性为整组类指定序列化 traits. 考虑以下名字-值对的包装:
template<class T>
struct nvp : public std::pair<const char *, T *>
{
...
};
它用于 XML 存档,将一个名字关联到一个类型 T 的变量。该数据类型不需要跟踪也不需要版本化。所以你可能会这样写:
BOOST_CLASS_IMPLEMENTATION(nvp<T>, boost::serialization::level_type::object_serializable)
BOOST_CLASS_TRACKING(nvp<T>, boost::serialization::track_never)
测试这两个宏定义会发现,它们无法扩展为正确的代码,由于用了一个模板参数。所以不能用这些宏,而要使用原始的定义:
template<class T>
struct implementation_level<nvp<T> >
{
typedef mpl::integral_c_tag tag;
typedef mpl::int_<object_serializable> type;
BOOST_STATIC_CONSTANT(
int,
value = implementation_level::type::value
);
};
// nvp 对象通常创建于栈中,无需跟踪
template<class T>
struct tracking_level<nvp<T> >
{
typedef mpl::integral_c_tag tag;
typedef mpl::int_<track_never> type;
BOOST_STATIC_CONSTANT(
int,
value = tracking_level::type::value
);
};
来为所有由模板
nvp<T>
生成的类指定序列化 traits
注意,只能在可以正确支持模板偏特化的编译器上使用以上方法来为模板指定 traits. 你的第一个想法可能是这样写:
如果你想让你的代码和存档可以移植到其它平台,这样写就会有问题。这样对象的序列化行为会因为不同的平台而有所不同。这意味着在一个平台保存的对象将不能在另一个平台上导入。换句话说,存档是不可移植的。#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template<class T> struct implementation_level<nvp<T> > { ... // 见前文 }; // nvp
对象通常创建于栈中,无需跟踪
template<class T> struct tracking_level<nvp<T> > { ... // 见前文 }; #endif
解决的办法是为用户类型创建另一个指定序列化 traits 的方法。对 名字-值对 的序列化就是一个例子。
特别地,可以让这个模板派生自一个特殊类 boost::serialization::traits
, 该类指定了序列化 traits 的一个特定组合。在查找序列化 traits 时,本库首先检查该类是否被用作基类。若是,则使用相应的 traits. 否则,使用标准的缺省值。通过派生自一个序列化 traits 类而不是依赖于模板偏特化,你可为一个模板指定序列化 traits 而且这些 traits 可以跨越所有已知平台。
该 traits 模板的符号特征如下:
template<
class T,
int Level,
int Tracking,
unsigned int Version = 0,
class ETII = BOOST_SERIALIZATION_DEFAULT_TYPE_INFO(T)
>
struct traits
其中的模板参数应根据下表进行赋值:
参数 | 描述 | 允许的值 | 缺省值 |
---|---|---|---|
T | 目标类 | 类名 | 无 |
Level | 实现级别 | not_serializable | 无 |
Tracking | 跟踪级别 | track_never | 无 |
Version | 类版本 | 无符号整数 | 0 |
ETTI | type_info 实现 | extended_type_info_typeid | 缺省 type_info 实现 |