optional< T>

c++14中将包含一个std::optional类,optional< T>内部存储空间可能存储了T类型的值也可能没有存储T类型的值。当optional< T>被初始化之后,可以通过operator bool() 获得true的返回值,否则返回值为false,这样可以知道该optional内部是否有合法的一个T对象,进而继续访问。

    optional<int> op; //未初始化,operator bool()为false
if (op)
cout << *op << endl;
optional<int> op1 = 1;
if (op) //经过初始化,返回true
cout << *op1 << endl;
c++11实现optional

optional< T>要容纳T类型的对象,因此需要一个缓冲区来保存,该缓冲区可以使用普通的char数组,但是char xx[]是一字节对齐,xx很有可能不在MyClass对齐的位置上。这样调用placement new构造内存块,可能会引起效率问题或出错,因此需要用内存对齐的缓冲区 std::aligned_storage.

    template<std::size_t Len, std::size_t Align>
struct aligned_storage;
Len表示所存储类型的size,通过sizeof(T)获得;Align表示该类型内存对齐的大小,通过std::alignment_of<T>::value获得。

std::aligned_storage一般和placement new结合起来使用:

struct A{
int avg;
A(int a, int b):avg((a+b)/2){};
};
typedef std::aligned_storage<sizeof(A), std::aligenment_of<A>::value>::type Aligned_A;
int main(){
Aligned_A a, b; //获得了两块内存区,大小和对齐方式指定
new (&a)A(10,20); //placement new,在内存块a处 构造了一个A对象
b = a;
return 0;
}
Optional的实现【代码均参考网上】
#include<type_traits>
#include<iostream>
#include<string>
#include<map>
using namespace std;
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*()
{
if (IsInit())
{
return *((T*)(&m_data));
} throw std::logic_error("is not init");
} T const& operator*() const
{
if (IsInit())
{
return *((T*)(&m_data));
} throw std::logic_error("is not init");
} 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;
}; class MyClass{
public:
MyClass(int a, int b) :
x_(a), y_(b){};
void print(){
cout << "x_ = " << x_ << endl;
cout << "y_ = " << y_ << endl;
}
private:
int x_;
int y_;
};
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, 1));
mymap.insert(std::make_pair(c, 2)); auto it = mymap.find(a);
cout << it->second << endl; Optional<MyClass> d;
d.emplace(10, 20);
(*d).print();
} int main(){
TestOptional();
return 0;
}

最新文章

  1. CSS总则。
  2. 搜索引擎 ElasticSearch 之 步步为营 【主目录】
  3. 原生JS:String对象详解
  4. matlab 功率谱分析
  5. sendmessage和postmessage的区别
  6. s3c6410_MMU地址映射过程详述
  7. iOS8 超简单的设置圆角按钮 ImageView等UIView
  8. P1689: [Usaco2005 Open] Muddy roads 泥泞的路
  9. Leetcode#138 Copy List with Random Pointer
  10. C.xml
  11. 51nod1269 B君的圆锥
  12. linux常用命令详解
  13. PL/SQL developer 使用技巧汇总
  14. ContextMenuStrip控件
  15. HTML+CSS基础学习笔记(2)
  16. ubuntu下编译源码级QT
  17. .NET 3.5(5) - LINQ查询操作符之Select、Where、OrderBy、OrderByDescending
  18. IOS 表视图(UITableVIew)的使用方法(2)名单的分段显示
  19. oracle 主键自动增长
  20. day 14 递归、匿名函数、内置函数

热门文章

  1. CAD常见问题
  2. QT4.8.5 QComboBox 增加选择菜单记录
  3. ramdisk文件系统制作
  4. lua 的io操作,非常详细
  5. flv网页视频播放
  6. 判断一个string是否以数字开头
  7. Qt信号槽的一些事
  8. e636. Listening to All Key Events Before Delivery to Focused Component
  9. UIView的几个枚举定义
  10. 【Java面试题】35 List, Set, Map是否继承自Collection接口?