当前位置: 首页 > article >正文

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;
}


http://www.kler.cn/a/406185.html

相关文章:

  • centos一键卸载docker脚本
  • Docker核心概念总结
  • 树莓派2 安装raspberry os 并修改成固定ip
  • 如何利用ChatGPT加速开发与学习:以BPMN编辑器为例
  • 大数据实战——MapReduce案例实践
  • 解决IDEA报包不存在,但实际存在的问题
  • 【AIGC】ChatGPT提示词Prompt解析:拒绝的艺术:如何优雅地说“不“
  • 如何为PDF文件创建口令密码
  • 如何在MATLAB中实现图像自动分割
  • C语言基础学习:抽象数据类型(ADT)
  • 远程服务器Docker使用本地代理加速访问外部资源
  • gitlab:使用脚本批量下载项目,实现全项目检索
  • 关于Linux中线程优先级的问题探讨
  • 【Linux】-学习笔记04
  • [ruby on rails] 安装docker
  • 量化交易系统开发-实时行情自动化交易-4.3.1.跨市场套利策略实现
  • JAVA中的Lamda表达式
  • Lua 实现继承的一种方式
  • n、nvm、nrm、pnpm、yarn各种指令大全
  • 设计模式之 责任链模式
  • .net 7.0 解决“The keyword field is required”的问题
  • 面向服务的软件工程——巨详细讲解商务流程建模符号 (BPMN),一篇章带你入门BPMN!!!(week1)
  • 在win10环境部署opengauss数据库(包含各种可能遇到的问题解决)
  • 基于RTEMS项目学习waf build system
  • 「漏洞复现」ArcGIS 地理信息系统 任意文件读取漏洞
  • pycharm在使用conda虚拟环境时Terminal爆红问题