c++11实现c++14的optional
c++14中将包含一个std::optional类,它的功能和用法和boost的optional类似。optional<T>内部存储空间可能存储了T类型的值也可能没有存储T类型的值,只有当optional被T初始化之后,这个optional才是有效的,否则是无效的,它实现了未初始化的概念。
optional的应用场景
函数返回无效对象
有时根据某个条件去查找对象时,如果查找不到对象时就会返回一个无效值,这不表明函数执行失败,而是表明函数正确执行了,但是结果却不是有用的值,这时就可以返回一个未初始化的optional对象出去,在外面判断这个optional对象是否有效对象是否被初始化,如果没有被初始化就表明这个值是无效的。
boost中的optional就实现了这种未初始化的概念,boost.optional的基本用法很简单:
optional<int> op;
if(op)
cout<<*op<<endl; optional<int> op1 = ;
if(op1)
cout<<*op1<<endl;
第一个op由于没有被初始化,所以它是一个无效值,将不会输出打印信息,第二个op被初始化为1,所以它是一个有效值,将会输出1。optional经常用于函数返回值,像boost.property_tree中就有很多optional接口(关于boost.property_tree可以参考我前面博文的介绍:),比如get_child_optional接口,返回一个optional<ptree>对象,外面需要判断它是否是一个有效值来确定是否取到了对应的子节点。
c++11实现optional
c++11中目前还没有optional,在c++14中将会增加std::optional功能和用法和boost.optional类似。在c++14中的std::optional出来之前,如果不想依赖boost库的话,就用c++11实现一个optional,也不是难事。
c++11实现optional需要注意的问题
1.内部存储空间
由于optional<T>需要容纳T的值,所以需要一个缓冲区保存这个T,这个缓冲区不能用普通的char数组,需要用内存对齐的缓冲区,这里还是采用std::aligned_storage,关于这个可以参考我前面的博文中对std::aligned_storage的讨论。
2.拷贝构造函数和赋值构造函数
需要注意拷贝和赋值时,内部状态和缓冲区销毁的问题。内部状态用来标示该optional是否被初始化,当已经初始化时需要先将缓冲区清理一下。需要增加右值版本优化效率。
来看看具体的实现吧:
#include <type_traits> template<typename T>
class Optional
{
using data_t = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
public:
Optional() : m_hasInit(false) {}
Optional(const T& v)
{
Create(v);
} Optional(T&& v) : m_hasInit(false)
{
Create(std::move(v));
} ~Optional()
{
Destroy();
} Optional(const Optional& other) : m_hasInit(false)
{
if (other.IsInit())
Assign(other);
} Optional(Optional&& other) : m_hasInit(false)
{
if (other.IsInit())
{
Assign(std::move(other));
other.Destroy();
}
} Optional& operator=(Optional &&other)
{
Assign(std::move(other));
return *this;
} Optional& operator=(const Optional &other)
{
Assign(other);
return *this;
} template<class... Args>
void emplace(Args&&... args)
{
Destroy();
Create(std::forward<Args>(args)...);
} bool IsInit() const { return m_hasInit; } explicit operator bool() const { return IsInit(); } T& operator*()
{
return *((T*) (&m_data));
} T const& operator*() const
{
if (IsInit())
{
return *((T*) (&m_data));
} throw std::exception("");
} bool operator == (const Optional<T>& rhs) const
{
return (!bool(*this)) != (!rhs) ? false : (!bool(*this) ? true : (*(*this)) == (*rhs));
} bool operator < (const Optional<T>& rhs) const
{
return !rhs ? false : (!bool(*this) ? true : (*(*this) < (*rhs)));
} bool operator != (const Optional<T>& rhs)
{
return !(*this == (rhs));
}
private:
template<class... Args>
void Create(Args&&... args)
{
new (&m_data) T(std::forward<Args> (args)...);
m_hasInit = true;
} void Destroy()
{
if (m_hasInit)
{
m_hasInit = false;
((T*) (&m_data))->~T();
}
} void Assign(const Optional& other)
{
if (other.IsInit())
{
Copy(other.m_data);
m_hasInit = true;
}
else
{
Destroy();
}
} void Assign(Optional&& other)
{
if (other.IsInit())
{
Move(std::move(other.m_data));
m_hasInit = true;
other.Destroy();
}
else
{
Destroy();
}
} void Move(data_t&& val)
{
Destroy();
new (&m_data) T(std::move(*((T*) (&val))));
} void Copy(const data_t& val)
{
Destroy();
new (&m_data) T(*((T*) (&val)));
} private:
bool m_hasInit;
data_t m_data;
};
测试代码:
void TestOptional()
{
Optional<string> a("ok");
Optional<string> b("ok");
Optional<string> c("aa");
c = a;
if (c<a)
cout << "<" << endl; if (a == b)
cout << "=" << endl; map<Optional<string>, int> mymap;
mymap.insert(std::make_pair(a, ));
mymap.insert(std::make_pair(c, )); auto it = mymap.find(a);
cout << it->second << endl;
}
可以看到用法和boost.optional的用法保持一致,实现起来也比较简单。
如果你觉得这篇文章对你有用,可以点一下推荐,谢谢。
c++11 boost技术交流群:296561497,欢迎大家来交流技术。
c++11实现c++14的optional的更多相关文章
- 剑指offer19:按照从外向里以顺时针的顺序依次打印出每一个数字,4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
1 题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印 ...
- GCC 4.9.0 公布,提升 C++11 和 C++14 特性
from :http://www.oschina.net/news/51084/gcc-4-9-0 GCC 4.9.0 公布,此版本号是个主要版本号更新,包含了 GCC 4.8.x 系列和之前的 GC ...
- Effective Modern C++ 42 Specific Ways to Improve Your Use of C++11 and C++14
Item 1: Understand template type deduction. Item 2: Understand auto type deduction. Item 3: Understa ...
- [C/C++语言标准] ISO C99/ ISO C11/ ISO C++11/ ISO C++14 Downloads
语言法典,C/C++社区人手一份,技术讨(hu)论(peng)必备 ISO IEC C99 https://files.cnblogs.com/files/racaljk/ISO_C99.pdf IS ...
- [C/C++语言标准] ISO C99/ ISO C11/ ISO C++11/ ISO C++14/ISO C++17 Downloads
语言法典,C/C++社区人手一份,技术讨(hu)论(peng)必备 ISO IEC C99 https://files.cnblogs.com/files/racaljk/ISO_C99.pdf IS ...
- 第11月第14天 opengl yuv beginners-tutorials
1. Here is some snippets of code from my project 'movie player for iOS'. 1. fragment shader varying ...
- VMware Workstation 11 中 Ubuntu 14.04 的 VMware Tools 问题 :没有显示共享文件夹
症状:主要表现在Win7中用VM11安装的Ubuntu14.04中,安装完自带的VMware Tools之后,/mnt/hgfs 中没有前面已经设置好的共享文件夹. 仔细查看了安装过程,发现在 ...
- 如何让自己的Dev C++用上C++11,c++14标准
首先确保Dev C++版本是最新的5.11版 其实用C++11和C++14标准的语法去运行还是会出现结果的,最多warning一下 但完美主义者是不允许这样的 我们可以点击菜单栏的“工具”-> ...
- matlab中函数学习——11月14日
1.记录数组元素个数函数:numel() 解释:number of array 相当于 prod(size(A)) 2.添加路径: addpath('.\3rdparty\ksvd'); 3.pada ...
随机推荐
- 基于源码编译安装openssh
最近的,openssl/openssh等相继漏洞的暴露,让暴露在公网的linux.沦陷为肉鸡的正营... 没办法,还是升级版本... 00.openssh简介 OpenSSH 是一组安全远程的连接工 ...
- 请问实现MVC的框架有哪些,实现持久化操作的框架有哪些,还有类似于spring整合的框架又有哪些
2011-04-10 我知道MVC框架有struts.webWork; 持久化的有hibernate.ibatis,而进行整合的我只知道spring了 ------------------- 表示层框 ...
- Language and Compiler Features Since Delphi 7
from: http://edn.embarcadero.com/cn/article/34324 Language and Compiler Features Since Delphi 7 In ...
- 倒计时实现两种方法-NSTimer/GCD
#import "ViewController.h" @interface ViewController () @property (nonatomic ,strong)UIBut ...
- 解决flume运行中的一个异常问题!
今天在本地测试flume的exec 监控文件 分割的问题!!!遇到各种141异常问题! 怀疑是在切割文件的时候超过了监控文本的时间,导致flume异常退出,,,所以增加了keep-alive 时 ...
- 【java】JVM的内存区域划分
学过C语言的朋友都知道C编译器在划分内存区域的时候经常将管理的区域划分为数据段和代码段,数据段包括堆.栈以及静态数据区.那么在Java语言当中,内存又是如何划分的呢? 由于Java程序是交由JVM执行 ...
- Windows ElasticSearch中文分词配置
elasticsearch官方只提供smartcn这个中文分词插件,效果不是很好,好在国内有medcl大神(国内最早研究es的人之一)写的两个中文分词插件,一个是ik的,一个是mmseg的,下面分别介 ...
- iOS自己主动化測试的那些干货
前言 假设有測试大佬发现内容不正确.欢迎指正,我会及时改动. 大多数的iOS App(没有持续集成)迭代流程是这种 也就是说.測试是公布之前的最后一道关卡.假设bug不能在測试中发现,那么bug 就会 ...
- OPENSSL编程起步
原文链接: http://blog.csdn.net/itmes/article/details/7711076 WINDOWS平台下OPENSSL的编译和安装使用 OPENSSL是开放源代码的,可以 ...
- 测试rp文件
正文: 测试我的博客,我的资源在github上! 地址:https://github.com/gmqllf/tx-lcn