zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Codeforces Round #625 (Div. 2, based on Technocup 2020 Final Round)(A-C题解)
    最小生成树
    并查集
    字符串的匹配算法
    CTU Open Contest 2019 AB题
    Codeforces Round #624 (Div. 3)(题解)
    Educational Codeforces Round 53 (Rated for Div. 2) (前五题题解)
    Lyft Level 5 Challenge 2018
    终于在博客写完第一篇题解啦
    Codeforces Round #519 by Botan Investments(前五题题解)
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/4811429.html
Copyright © 2011-2022 走看看