c++11的动态类型
c++17引入了any 和 variant,可以将任意数据类型统一用any或variant类型表示,在开发中还是能够带来很多便利的。在c++11版本中,可以用下面这个例子,仿照实现一个Any类型。
#include <iostream>
#include <stdexcept>
#include <memory>
class UserData{
public:
UserData(){}
std::string operator()()
{
return m_name;
}
private:
std::string m_name="world";
};
class Any
{
public:
template<typename T>
Any(const T& val) noexcept : content(new Holder<T>(val)) {}
Any(const Any& other) noexcept : content(other.content ? other.content->Copy() : nullptr) {}
Any(Any&& other) noexcept :content(std::move(other.content)) {}
Any& operator=(const Any& other)
{
if (this == &other)
return *this;
content.reset(other.content ? other.content->Copy() : nullptr);
return *this;
}
template<typename T>
T& get() const
{
if (content.get() == nullptr)
{
throw std::exception_ptr();
}
if (typeid(T).hash_code() != content->TypeID())
{
throw std::bad_cast();
}
return static_cast<Holder<T>*>(content.get())->value;
}
std::string TypeName() const
{
if (content)
return content->TypeName();
return "";
}
size_t TypeID()
{
if (content)
return content->TypeID();
return 0;
}
private:
struct Base {
virtual ~Base() {}
virtual Base* Copy() const = 0;
virtual size_t TypeID() const = 0;
virtual const char* TypeName() const = 0;
};
template<typename T>
struct Holder :public Base
{
Holder<T>() = delete;
Holder<T>(const T& val) : value(val), typid(typeid(T).hash_code()), typname(typeid(T).name()) {}
~Holder<T>() {}
Base* Copy() const override { return new Holder<T>(value); }
size_t TypeID() const override { return typid; }
const char* TypeName() const override { return typname; }
T value;
size_t typid;
const char* typname;
};
std::unique_ptr<Base> content;
};
int main()
{
int iVal = 10;
Any param = iVal;
int& iv = param.get<int>();
iv = 100;
std::cout<<param.TypeName()<<", val="<<param.get<int>()<<std::endl;
std::string sVal="hello";
param = sVal;
std::cout<<param.TypeName()<<", val="<<param.get<std::string>()<<std::endl;
double dVal = 101.21;
Any paramd = dVal;
param = paramd;
std::cout<<param.TypeName()<<", val="<<param.get<double>()<<std::endl;
UserData data;
param = data;
UserData& dt = param.get<UserData>();
std::cout<<param.TypeName()<<", val="<<dt()<<std::endl;
return 0;
}