1. 程式人生 > >C++11 Boost Any類實現

C++11 Boost Any類實現


#include "pch.h"
#include <iostream>
#include <memory>
#include <typeindex>

using namespace std;

/*
	類似於boost Any類的實現
*/
struct Any {
public:
	Any(void) :m_tpIndex(type_index(typeid(void))) {}
	Any(Any& that) :m_ptr(that.Clone()), m_tpIndex(that.m_tpIndex) {}
	Any(Any&& that) :m_ptr(move(that.m_ptr)), m_tpIndex(that.m_tpIndex) {}
	// 建立智慧指標時,對於一般的型別,通過decay來移除引用和CV符,從而獲取原始型別
	template<typename U, class = typename enable_if<!is_same<typename decay<U>::type, Any>::value,U>::type>
		Any(U &&value):m_ptr(new Derived<typename decay<U>::type>(forward<U>(value))), m_tpIndex(type_index(typeid(typename decay<U>::type))) {}

	bool IsNull() const { return !bool(m_ptr); }
	template<class U>bool Is() const {
		return m_tpIndex == type_index(typeid(U));
	}

	// 將Any轉換成實際的型別
	template<class U>
	U& AnyCast()
	{
		if (!Is<U>())
		{
			cout << "can not cast " << typeid(U).name() << " to " << m_tpIndex.name() << endl;
			throw bad_cast();
		}
		auto derived = dynamic_cast<Derived<U>*> (m_ptr.get());
		return derived->m_value;
	}

	Any operator=(const Any& a)
	{
		if (m_ptr == a.m_ptr)
			return *this;
		m_ptr = a.Clone();
		m_tpIndex = a.m_tpIndex;
		return *this;
	}
private:
	struct Base;
	typedef unique_ptr<Base> BasePtr;
	struct Base
	{
		virtual ~Base() {}
		virtual BasePtr Clone() const = 0;
	};

	template<typename T>
	struct Derived :Base 
	{
		template<typename U>
		Derived(U&& value) :m_value(forward<U>(value)) {}
		BasePtr Clone() const {
			return BasePtr(new Derived<T>(m_value));
		}
		T m_value;
	};

	BasePtr Clone() const
	{
		if (m_ptr != nullptr)
		{
			return m_ptr->Clone();
		}
		return nullptr;
	}

	BasePtr m_ptr;
	type_index m_tpIndex;
};
int main()
{
	Any n;
	auto r = n.IsNull(); // true
	string s1 = "hello";
	n = s1;
	n.AnyCast<int>();    // 轉換失敗將丟擲異常
	Any n1 = 1;
	n1.Is<int>();		// true;
}