A simple implementation of 'any' type in c++11.
refer to cnblogs.com/qiconmos/p/3420095.html
#include <memory> // for unique_ptr | |
#include <utility> // for forward | |
#include <typeindex> // for type_index | |
//Any, refere to cnblogs.com/qiconmos/p/3420095.html, keyword: c++11 any | |
class Any { | |
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) return m_ptr->clone(); | |
return nullptr; | |
} | |
BasePtr m_ptr; | |
std::type_index m_tpIndex; | |
public: | |
Any(void) : m_tpIndex(std::type_index(typeid(void))) {} | |
Any(const Any &a) : m_ptr(a.clone()), m_tpIndex(a.m_tpIndex) {} | |
Any(Any &&a) : m_ptr(std::move(a.m_ptr)), m_tpIndex(a.m_tpIndex) {} | |
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); } | |
bool isValid() const { return bool(m_ptr); } | |
template <class U> bool is() const { | |
return m_tpIndex == std::type_index(typeid(U)); | |
} | |
template <class U> | |
U & cast() { | |
if (!is<U>()) throw std::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; | |
} | |
const char* typeName() const { return m_tpIndex.name(); } | |
}; | |
#include <string> | |
#include <iostream> | |
int main() { | |
int int_aa = 11; | |
std::string hello("hello"); | |
Any aa(int_aa); | |
Any bb(hello); | |
Any cc(&hello); | |
std::cout << "any of int = " << aa.cast<int>() << std::endl; | |
std::cout << "any of string = " << bb.cast<std::string>() << std::endl; | |
std::cout << "any of string* = " << *(cc.cast<std::string*>()) << std::endl; | |
} | |
// g++ -Wall -std=c++11 simple-any.cpp |