c++11实现optional

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

 

原文链接: https://www.cnblogs.com/gtarcoder/p/4811429.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    c++11实现optional

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/221911

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月13日 上午11:29
下一篇 2023年2月13日 上午11:29

相关推荐