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