boost 实用工具 optional学习

optional

1
2
#include<boost/optional.hpp>
using namespace boost;

“无意义”的值

函数正确执行,结果不一定是有效的返回值,也可能是“无意义”的值。例如,求一个值得倒数,传入参数为0。

类摘要

optional像一个仅能存放一个元素的容器,实现“未初始化”的概念:如果元素未初始化,容器就是空的,否则,容器内就是有效的、已经初始化的值。

optional类摘要

操作函数

optional的模版类型参数T可以是任何类型,但必须是可拷贝构造的。创建optional对象的方法:

  • 无参optional()或者optional(boost::none)构造未初始化optional对象。boost::none是一个类似空指针的none_t类型常量,表示未初始化。
  • optional(v)构造一个已初始化的optional对象,其值未v的拷贝。如果模版类型为T&,optional内部持有对引用的包装。
  • optional(condition, v)根据条件condition来构造optional对象,如果条件成立则初始化为v,否则为未初始化。
  • optional支持拷贝构造和赋值操作,可以从另一个optional对象构造。可以给optional对象赋none值,恢复初未初始化状态。

optional采用指针语义来访问内部保存的额元素,因此optional未初始化的行为就像一个空指针。optional重载了operator*和operator->实现与指针相同的操作,get()和get_ptr()可以以函数形式获得元素的引用的指针。

成员函数get_value_or(default)是一个特别的访问函数,保证返回一个有效值,如果optional已初始化,返回内部元素,否则返回default。

optional用隐式类型转换进行bool测试(用于条件判断),就像对一个指针的判断。

optional支持比较运算,包括==、!=、<、>、<=、>=。optional进行”深比较”,同时加入对未初始化的判断。

用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
optional<double> calc(int x)
{
return optional<double>(x!=0, 1.0/x);
}

//optional
void TestOptional()
{
optional<int> op0;
optional<int> op1(op0);
assert(!op0);
assert(op0==op1);
assert(op1.get_value_or(253) == 253);

optional<string> ops("test");
cout<<*ops<<endl;

vector<int> v(10);
optional<vector<int> &> opv(v);
assert(opv);

opv->push_back(5);
assert(opv->size() == 11);

opv = none;
assert(!opv);

optional<double> d = calc(10);
if(d)
{
cout<<*d<<endl;
}

BOOST_AUTO(x, make_optional(5)); //工厂函数
cout<<*x<<endl;

return ;
}

工厂函数

optional提供工厂函数make_optional(),根据参数类型自动推导optional的类型,辅助创建optional对象。

1
2
optional<T> make_optional(T const &v);
optional<T> make_optional(bool condition, T const &v);

make_optional()无法推导T引用类型的optional对象,如果需要一个optional的对象,不能使用make_optional函数。

高级议题

异常

optional同STL容器一样,值提供基本的异常保证,不会超过被包装的类型T,它自身不会抛出任何异常,只有在T构造时可能会抛出异常。

就地创建

optional要求类型T具有拷贝语义,因为optional内部会保存值得拷贝,但很多复杂对象的拷贝代价很高,而仅仅是个拷贝的临时用途,因此optional库提出“就地创建”的概念,可以不要求类型具有拷贝语义,直接用构造函数所需的参数创建对象。boost库in_place_factory。

引用类型

optional的模版参数类型可以是引用(T&),在很多方面和原始类型T有不同(无法使用就地创建、就地赋值,可以声明时不指定初值、在赋值时转移包装的对象,而不是对原包装的对象赋值),