forked from qicosmos/cosmos
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Any.hpp
92 lines (74 loc) · 1.98 KB
/
Any.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#pragma once
#include <memory>
#include <typeindex>
#include <exception>
#include <iostream>
struct Any
{
Any(void) : m_tpIndex(std::type_index(typeid(void))) {}
Any(const Any& that) : m_ptr(that.Clone()), m_tpIndex(that.m_tpIndex) {}
Any(Any && that) : m_ptr(std::move(that.m_ptr)), m_tpIndex(that.m_tpIndex) {}
//创建智能指针时,对于一般的类型,通过std::decay来移除引用和cv符,从而获取原始类型
template<typename U, class = typename std::enable_if<!std::is_same<typename std::decay<U>::type, Any>::value, U>::type> Any(U && value) : m_ptr(new Derived < typename std::decay<U>::type>(std::forward<U>(value))),
m_tpIndex(std::type_index(typeid(typename std::decay<U>::type))){}
bool IsNull() const { return !bool(m_ptr); }
template<class U> bool Is() const
{
return m_tpIndex == std::type_index(typeid(U));
}
//将Any转换为实际的类型
template<class U>
U& AnyCast()
{
if (!Is<U>())
{
std::cout << "can not cast " << typeid(U).name() << " to " << m_tpIndex.name() << std::endl;
throw std::logic_error{"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;
}
Any& operator=(Any&& a)
{
if (m_ptr == a.m_ptr)
return *this;
m_ptr = std::move(a.m_ptr);
m_tpIndex = a.m_tpIndex;
return *this;
}
private:
struct Base;
typedef std::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(std::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;
std::type_index m_tpIndex;
};