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;
}

c++11实现optional的更多相关文章

  1. c++11::std::optional

    std::optional还有一个类似于智能指针的接口, 它可以显式转化为bool来表示std::optional是否有一个值. 指针的解引用操作符*和->都实现了, 但是没有std::bad_ ...

  2. c++11实现c++14的optional

    c++14中将包含一个std::optional类,它的功能和用法和boost的optional类似.optional<T>内部存储空间可能存储了T类型的值也可能没有存储T类型的值,只有当 ...

  3. 使用Optional处理null

    一.聊聊NullPointerException   相比做Java开发的,见到NullPointerException肯定不陌生吧,可以说见到它深恶痛绝.在开发时认为不会出现NullPointerE ...

  4. 【Java8新特性】Optional 类

    概述 Optional 类是一个可以为null的容器对象.如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象. Optional 是个容器:它可以保存类型T的值,或者 ...

  5. ANDROID5.0触摸屏校准

    1.校准原理: 1)首先生成校准用的参数,可以适用tslib生成校准参数,也可以使用校准app生成:使用校准app进行校准对使用者要求比较低,使用者可以不用学习复杂的命令:本文使用app方式 2)生成 ...

  6. 使用jQuery.FileUpload和Backload自定义控制器上传多个文件

    当需要在控制器中处理除了文件的其他表单字段,执行控制器独有的业务逻辑......等等,这时候我们可以自定义控制器. 通过继承BackloadController □ 思路 BackloadContro ...

  7. Java8 Stream代码详解+BenchMark测试

    Java8 Stream基础.深入.测试 1.基本介绍 1.创建方式 1.Array的Stream创建 1.直接创建 // main Stream stream = Stream.of("a ...

  8. Java 面试知识点解析(四)——版本特性篇

    前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...

  9. Java基础系列-Stream

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/10748817.html 一.概述 Stream操作简称流操作,这里的流与IO流毫无关系, ...

随机推荐

  1. 【Unity】用代码给按钮动态添加点击事件

    问题:多数情况下用UGUI的Button控件身上的OnClick()列表可以指明该按钮点击后触发的回调.现在想要调用自定义脚本里的方法,当这个脚本挂在Button所属的Canvas身上时,传入Canv ...

  2. ExtJs 常用小技巧备忘录

    1. ExtJs 给fieldLabel与fieldInput添加样式{给Input标签加入图标}http://www.w3school.com.cn/cssref/pr_background.asp ...

  3. Android——FileOutputStream与openFileOutput()的区别分析【第一个用于文件存储,第二个用于SD卡存储】【转】

    本文实例分析了Android编程中FileOutputStream与openFileOutput()的区别.分享给大家供大家参考,具体如下: openFileOutput() 首先给大家介绍使用文件如 ...

  4. 使用子查询可提升 COUNT DISTINCT 速度 50 倍

    注:这些技术是通用的,只不过我们选择使用Postgres的语法.使用独特的pgAdminIII生成解释图形. 很有用,但太慢 Count distinct是SQL分析时的祸根,因此它是我第一篇博客的不 ...

  5. 25+开源的在线购物软件(PHP, JavaScript 和 ASP.Net)

    25 +免费开源的电子商务解决方案,提供了建立一个在线购物所有主要功能,并能够连接到一个支付处理系统1. Magento Magento是一套专业开源的PHP电子商务系统.Magento设计得非常灵活 ...

  6. 第三百一十八节,Django框架,信号

    第三百一十八节,Django框架,信号 Django中提供了“信号调度”,用于在框架执行操作时解耦.通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者. 也就是当程序有指定动作时, ...

  7. 应当将指针变量用“==”或“!=”与 NULL 比较

    应当将指针变量用“==”或“!=”与 NULL 比较. 指针变量的零值是“空”(记为 NULL). 尽管 NULL 的值与 0 相同,但是两者意义不 同. 假设指针变量的名字为 p,它与零值比较的标准 ...

  8. MVC演化 (转至http://www.cnblogs.com/wubaiqing/archive/2011/10/26/2225438.html)

    MVC已经成为我们最常误用的模式,人们之所以常常误用MVC,很大程度上是因为混淆了不同的MVC变体. Classic MVC Classic MVC 大概上世纪七十年代,Xerox PARC的Tryg ...

  9. Windows App开发之集成设置、帮助、搜索和共享

    应用设置和应用帮助 "设置"合约 上一节中我们学习了怎样将应用设置保存到本地.这样的方式是通过在App内加入设置选项,这里另一种方式. 微软将其称为"设置"合约 ...

  10. 新兵训练营课程——环境与工具Java[转]

    原文地址:http://weibo.com/p/1001643874239169320051 程序员在开发过程中会用到很多工具来提升开发和协作效率,这次介绍的是目前微博平台在开发过程中用到的一些工具, ...