进化版:一个C++模板工厂的编译问题的解决。针对第三方库的构造函数以及追加了的对象构造函数。牵扯到重载、特化等

news2024/9/19 14:28:03

原始版本在这里

一个C++模板工厂的编译问题的解决。针对第三方库的构造函数以及追加了的对象构造函数。牵扯到重载、特化等-CSDN博客

问题

1、关于类型的判断,适应性不强

比如template <typename T>IsFarElementId<>,目前只能判断FarElementId,如果推导出FarElementId&&并传给它,它就推导为false

2、如何去除重载函数

不能接收/判断所有的类型,比如接收ElementId的函数,就接收不了右值类型比如ElementId&&的函数,那么就得添加一个重载函数,用来接收ElementId&&。

相应的,还有其他组合,比如const std::wstring&等。它们内部的逻辑都是一样的,总不能给每个组合都添加对应的函数吧。

问题就变成了不管是ElementId&还是ElementId&&,想让它们都走一个函数。

第一个问题

先上最后的结果。

struct EEhFactory
{
    ///@code{.unparsed}
    ///此函数的功能:
    ///  创建EditElementHandle的指针对象
    ///  最泛化版本
    ///@endcode 
    ///@return   true:成功 false:失败
    ///@author Simon.Zou @date 2024/02/20
    template <typename ... Args>
    static std::shared_ptr<DgnPlatform::EditElementHandle>/*HCHXKERNEL::EditElementHandlePtr*/
        Create(Args&& ... args)
    {
        return std::make_shared<DgnPlatform::EditElementHandle>(std::forward<Args>(args)...);
    }

    ///@code{.unparsed}
    ///此函数的功能:
    ///  创建EditElementHandle的指针对象,并且Schedule写入XA数据:sortFlag
    ///  最泛化版本
    ///@endcode 
    ///@return   true:成功 false:失败
    ///@author Simon.Zou @date 2024/02/20
    template <typename ... Args>
    static std::shared_ptr<DgnPlatform::EditElementHandle>/*HCHXKERNEL::EditElementHandlePtr*/
        CreateWithSortFlag(
            UInt64 sortFlag, ///<IN uuid
            Args&& ... args  ///< parameters
        )
    {
        auto eeh = std::make_shared<EditElementHandle>(std::forward<Args>(args)...);
        HCHXKERNEL::SortEEh::SetFlagForSort(sortFlag, *eeh);

        return eeh;
    }

    template<typename T>
    struct _IsUInt64 : std::false_type
    {};

    template<>
    struct _IsUInt64<UInt64> : std::true_type
    {};

    template<class _Ty>
    struct IsUInt64
        : _IsUInt64<typename std::decay<_Ty>::type>
    {	// determine whether _Ty is UInt64
    };

    template<typename T>
    struct _IsElementId : std::false_type
    {};

    template<>
    struct _IsElementId<DgnPlatform::ElementId> : std::true_type
    {};

    template<class _Ty>
    struct IsElementId
        : _IsElementId<typename std::decay<_Ty>::type>
    {	// determine whether _Ty is IsElementId
    };

    template<typename T>
    struct _IsFarElementID : std::false_type
    {};

    template<>
    struct _IsFarElementID<DgnPlatform::DgnHistory::FarElementID> : std::true_type
    {};

    template<class _Ty>
    struct IsFarElementID
        : _IsFarElementID<typename std::decay<_Ty>::type>
    {	// determine whether _Ty is FarElementID
    };

    template<typename T>
    struct _IsWstring : std::false_type
    {};

    template<>
    struct _IsWstring<std::wstring> : std::true_type
    {};

    template<class _Ty>
    struct IsWstring
        : _IsWstring<typename std::decay<_Ty>::type>
    {	// determine whether _Ty is std::wstring
    };

    template<typename ParamType,
        std::enable_if<IsFarElementID<ParamType>::value>* = 0
    >
        static HCHXKERNEL::EditElementHandlePtr Create(ParamType&& farId) ///< 用FarElementId创建EditElementHandle
    {
        return MiscUtil::GetElementHandle(farId);
    }

    template <typename Param1st, typename Param2ndst, typename std::enable_if<IsElementId<Param1st>::value &&IsWstring<Param2ndst>::value, int>::type = 0>
    static HCHXKERNEL::EditElementHandlePtr Create(
        Param1st&& eid, ///<IN ElementId
        Param2ndst&& modelName ///< std::wstring model的名称
    )
    {
        DgnModelRefP modelRef = NULL;
        if (!MiscUtil::GetModelRefByName(&modelRef, modelName.c_str(), false, false))
            return NULL;

        //using eid_decayType = typename std::decay<Param1st>::type;
        //typename std::decay<Param1st>::type a;
        //TypeDisplayer<decltype(a)> aType;
        //return NULL;
        return EEhFactory::Create(eid, modelRef);
    }

    ///
    template<typename ParamType, std::enable_if<IsFarElementID<ParamType>::value>* = 0>
    static HCHXKERNEL::EditElementHandlePtr CreateWithSortFlag(UInt64 sortFlag, ParamType&& farId) ///< 用FarElementId创建EditElementHandle
    {
        HCHXKERNEL::EditElementHandlePtr eeh = MiscUtil::GetElementHandle(farId);
        if (eeh == NULL)
            return NULL;

        HCHXKERNEL::SortEEh::SetFlagForSort(sortFlag, *eeh);

        return eeh;
    }

    template <typename Param1st, typename Param2ndst, typename std::enable_if<IsElementId<Param1st>::value && IsWstring<Param2ndst>::value, int>::type = 0>
    static HCHXKERNEL::EditElementHandlePtr CreateWithSortFlag(
        UInt64 sortFlag, ///<IN uuid
        Param1st&& eid,///<IN ElementId
        Param2ndst&& modelName ///< std::wstring model的名称
    )
    {
        DgnModelRefP modelRef = NULL;
        if (!MiscUtil::GetModelRefByName(&modelRef, modelName.c_str(), false, false))
            return NULL;

        //using eid_decayType = typename std::decay<Param1st>::type;
        //typename std::decay<Param1st>::type a;
        //TypeDisplayer<decltype(a)> aType;
        //return NULL;
        auto eeh = EEhFactory::Create(eid, modelRef);
        HCHXKERNEL::SortEEh::SetFlagForSort(sortFlag, *eeh);

        return eeh;
    }
};


测试:
TEST(other, 2用EEHFactory的Create函数创建对象)
{
    if (EEhFactory::IsWstring<std::wstring&&>::value)
    {
        int i = 0;
        std::ignore = i;
    }

    if (EEhFactory::IsWstring<const std::wstring&>::value)
    {
        int i = 0;
        std::ignore = i;
    }

    if (EEhFactory::IsFarElementID<DgnPlatform::DgnHistory::FarElementID>::value)
    {
        int i = 0;
        std::ignore = i;
    }


    if (EEhFactory::IsFarElementID<DgnPlatform::DgnHistory::FarElementID&&>::value)
    {
        int i = 0;
        std::ignore = i;
    }

    if (EEhFactory::IsFarElementID<int>::value)
    {
        int i = 0;
        std::ignore = i;
    }


    if (1)
    {
        {
            DgnPlatform::ElementId eid0{ 0 };//, eid1{ 0 };
            std::wstring str{ L"" };
            auto editElementHandlePtr2 = EEhFactory::Create(eid0, str);
            auto editElementHandlePtr3 = EEhFactory::Create(eid0, std::wstring{ L"" }); //右值
        }

        {
            DgnPlatform::DgnHistory::FarElementID farId{ 0,0 };
            auto editElementHandlePtr0 = EEhFactory::Create(farId);
            auto editElementHandlePtr1 = EEhFactory::Create(DgnPlatform::DgnHistory::FarElementID{ 0,0 }); //右值
        }

        {
            ElementRefP elRef{ NULL };
            DgnModelRefP modelRef{ NULL };
            auto editElementHandlePtr1 = EEhFactory::Create(elRef, modelRef);
        }

        {
            DgnPlatform::ElementId eid0{ 0 };//, eid1{ 0 };
            DgnModelRefP modelRef = NULL;
            EEhFactory::Create(eid0, modelRef);
        }
    }

    if (1)
    {
        {
            UInt64 id = 1;
            DgnPlatform::ElementId eid0{ 0 };//, eid1{ 0 };
            std::wstring str{ L"" };
            auto editElementHandlePtr2 = EEhFactory::CreateWithSortFlag(id, eid0, str);
            auto editElementHandlePtr3 = EEhFactory::CreateWithSortFlag(id, eid0, std::wstring{ L"" });
        }

        {
            DgnPlatform::DgnHistory::FarElementID farId{ 0,0 };
            auto editElementHandlePtr0 = EEhFactory::CreateWithSortFlag(UInt64(1), farId);
            auto editElementHandlePtr1 = EEhFactory::CreateWithSortFlag(UInt64(1), DgnPlatform::DgnHistory::FarElementID{ 0,0 });
        }

        {
            ElementRefP elRef{ NULL };
            DgnModelRefP modelRef{ NULL };
            auto editElementHandlePtr1 = EEhFactory::CreateWithSortFlag(UInt64(1), elRef, modelRef);
        }

        {
            DgnPlatform::ElementId eid0{ 0 };//, eid1{ 0 };
            DgnModelRefP modelRef = NULL;
            EEhFactory::CreateWithSortFlag(UInt64(1), eid0, modelRef);
        }
    }

}

灵感来源

灵感来源,判断是否为浮点


template<typename T>
struct TypePrinter;

template<class T, class Enabled = void >
class A123;

template<class T>
class A123<T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
public:
    A123() { std::cout << "partial specialization\r\n"; }
}; // specialization for floating point types


int main()
{
    A123<double> a;
}

注意,stl中std::is_floating_point的实现,学习了。

通过继承的方式,把decay过的最“干净”的类型传给_Is_floating_point进行判断。
是个不错的主意。要不然得学习别人的经验呢。


// STRUCT TEMPLATE _Is_floating_point
template<class _Ty>
	struct _Is_floating_point
		: false_type
	{	// determine whether _Ty is floating point
	};

template<>
	struct _Is_floating_point<float>
		: true_type
	{	// determine whether _Ty is floating point
	};

template<>
	struct _Is_floating_point<double>
		: true_type
	{	// determine whether _Ty is floating point
	};

template<>
	struct _Is_floating_point<long double>
		: true_type
	{	// determine whether _Ty is floating point
	};

	// STRUCT TEMPLATE is_floating_point
template<class _Ty>
	struct is_floating_point
		: _Is_floating_point<remove_cv_t<_Ty>>::type
	{	// determine whether _Ty is floating point
	};

template<class _Ty>
	_INLINE_VAR constexpr bool is_floating_point_v = is_floating_point<_Ty>::value;

简化一下,看其主体实现

	// STRUCT TEMPLATE _Is_floating_point
template<class _Ty>
	struct _Is_floating_point
		: false_type
	{	// determine whether _Ty is floating point
	};

template<>
	struct _Is_floating_point<float>
		: true_type
	{	// determine whether _Ty is floating point
	};

...

	// STRUCT TEMPLATE is_floating_point
template<class _Ty>
	struct is_floating_point
		: _Is_floating_point<remove_cv_t<_Ty>>::type
	{	// determine whether _Ty is floating point
	};

template<class _Ty>
	_INLINE_VAR constexpr bool is_floating_point_v = is_floating_point<_Ty>::value;

那么,我们自己的版本就好办了

编译,没问题。


    template<typename T>
    struct _IsFarElementID : std::false_type
    {};

    template<>
    struct _IsFarElementID<DgnPlatform::DgnHistory::FarElementID> : std::true_type
    {};

    template<class _Ty>
    struct IsFarElementID
        : _IsFarElementID<typename std::decay<_Ty>::type>
    {	// determine whether _Ty is FarElementID
    };


测试
    if (EEhFactory::IsFarElementID<DgnPlatform::DgnHistory::FarElementID>::value)
    {
        int i = 0;
        std::ignore = i;
    }


    if (EEhFactory::IsFarElementID<DgnPlatform::DgnHistory::FarElementID&&>::value)
    {
        int i = 0;
        std::ignore = i;
    }

    if (EEhFactory::IsFarElementID<int>::value)
    {
        int i = 0;
        std::ignore = i;
    }

第二个问题

现在能判断出来,不管是ElementId还是ElmentId&&,亦或是ElementId&,都是ElementId了。

但我希望用一个函数来接收这些参数。不想为他们添加多余的函数进行重载比如ElementId&是一个函数,ElementId&&用另一个函数,虽然内部可能都是转发到一个函数身上。

万能引用和完美转发-CSDN博客

在引入万能引用之前,我们写接收引用的函数需要如下代码:

void func(int& a) {
    std::cout << "left" << '\n';
}
 
void func(int&& a) {
    std::cout << "right" << '\n';
}

我们需要写两个函数,以便可以使用func(a)和func(1)。而万能引用的存在使得仅需写一个函数即可同时支持这两种写法。这也是为什么需要万能引用。

上面的函数进行以下写法即为万能引用:

template<typename T>
void func1(T&& a)
{
    
}

为了验证这个函数是否能够接收左值和右值我们可以测试一下: 

#include <iostream>
 
void func(int& a) {
    std::cout << "left" << '\n';
}
 
void func(int&& a) {
    std::cout << "right" << '\n';
}
 
template<typename T>
void func1(T&& a)
{
    func(std::forward<T>(a));
}
 
int main()
{
    int a = 3;
    func1(3);
    func1(a);
 
    return 0;
}

结果如下:

a4ae9806760b47f4b9e8597b6752df72.png

那么,思路就来了,挑一个接收FarElementId的吧

唯一的变化就是确保形参里是&&的形式:ParamType&& farId
它在模板里既可以接收左值,又可以接收右值

template<typename ParamType,
        std::enable_if<IsFarElementID<ParamType>::value>* = 0
    >
        static HCHXKERNEL::EditElementHandlePtr Create(ParamType&& farId) ///< 用FarElementId创建EditElementHandle
    {
        return MiscUtil::GetElementHandle(farId);
    }

测试代码:
{
DgnPlatform::DgnHistory::FarElementID farId{ 0,0 };
auto editElementHandlePtr0 = EEhFactory::Create(farId);
auto editElementHandlePtr1 = EEhFactory::Create(DgnPlatform::DgnHistory::FarElementID{ 0,0 }); //右值
}

编译通过。这个函数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1973709.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

达梦数据库的系统视图v$cacheitem

达梦数据库的系统视图v$cacheitem 达梦数据库的系统视图V$CACHEITEM的作用是显示缓存中的项信息&#xff0c;在 ini 参数 USE_PLN_POOL !0 时才统计。这个视图帮助数据库管理员监控和分析缓存的使用情况&#xff0c;优化数据库性能。通过查询V$CACHEITEM视图&#xff0c;可以获…

ai web 1.0靶机漏洞渗透详解

一、导入靶机 解压下载好的靶机&#xff0c;然后打开VMware&#xff0c;点击文件》打开》找到刚刚解压的靶机点击下面的文件》打开 确认是靶机的网络连接模式是NAT模式 二、信息收集 1、主机发现 在本机的命令窗口输入ipconfig查看VMnet8这块网卡&#xff0c;这块网卡就是虚…

案例分享—国外优秀ui设计作品赏析

国外UI设计创意迭出&#xff0c;融合多元文化元素&#xff0c;以极简风搭配动态交互&#xff0c;打造沉浸式体验&#xff0c;色彩运用大胆前卫&#xff0c;引领界面设计新风尚 同时注重用户体验的深度挖掘&#xff0c;通过个性化定制与智能算法结合&#xff0c;让界面不仅美观且…

代码随想录第十八天|动态规划(2)

目录 01背包问题——二维数组 01背包问题——一维数组 LeetCode 416. 分割等和子集 LeetCode 1049. 最后一块石头的重量 II LeetCode 494. 目标和 LeetCode 474. 一和零 总结 01背包问题——二维数组 有n件物品和一个最多能放入重量为w的背包。第i件物品的重量是weight…

web基础之CSS

web基础之CSS 文章目录 web基础之CSS一、CSS简介二、基本用法2、CSS应用方式2.1 行内样式2.2内部样式2.3外部样式 三、选择器1、标签选择器2、类选择器3、ID选择器4、选择器的优先级 四、常见的CSS属性1、字体属性2、文本属性3、背景属性4、表格属性5、盒子模型的属性6、定位 总…

LabVIEW激光主动探测系统

开发了一种基于LabVIEW的高性能激光主动探测控制与处理系统的设计与实现。该系统充分利用了LabVIEW的多线程和模块化设计优势&#xff0c;提供了一套功能完整、运行高效且稳定的解决方案&#xff0c;适用于高精度激光探测领域。 项目背景 激光主动探测技术利用激光作为主动光源…

dp专题(二)

洛谷&#xff1a;B3626 跳跃机器人 题目描述 地上有一排格子&#xff0c;共 nn 个位置。机器猫站在第一个格子上&#xff0c;需要取第 nn 个格子里的东西。 机器猫当然不愿意自己跑过去&#xff0c;所以机器猫从口袋里掏出了一个机器人&#xff01;这个机器人的行动遵循下面…

【面试题】【C语言】寻找两个正序数组的中位数

寻找两个正序数组的中位数 仅供学习 题目 算法时间复杂度 二分查找算法&#xff0c;时间复杂度为 O(log(min(m, n)))&#xff0c;其中 m 和 n 分别是两个数组的长度。 子函数 查找两个数字的最大值 int max(int a, int b) {return a > b ? a : b; }查找两个数字的最小…

ubuntu20.04搭建RUST开发环境并与C语言交互

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 ubuntu20.04搭建RUST开发环境并与C语言交互 前言开战一、确认环境版本二、环境搭建三、hello world&#xff01;四、跟c语言进行交互1.rust调用C静态库2.C调用rust库 总结参考…

LDR6500:小封装,易设计外围简单OTG数据+充电实现原理

移动设备的普及与功能日益丰富的今天&#xff0c;OTG&#xff08;USB On-The-Go&#xff09;转接器作为连接移动设备与外部设备的桥梁&#xff0c;其重要性不言而喻。而LDR6500&#xff0c;作为乐得瑞科技精心打造的一款USB-C DRP&#xff08;Dual Role Port&#xff0c;双角色…

vue3修改带小数点的价格数字:小数点的前后数字,要分别显示成不同颜色和大小!已经封装成组件了!

需求&#xff1a; 修改带小数点的价格数字&#xff1a;小数点的前后数字&#xff0c;要分别显示成不同颜色和大小&#xff01;已经封装成组件了&#xff01; 效果&#xff1a; 前面大&#xff0c;后面小 代码&#xff1a; 组件&#xff1a; <!--修改小数点前后数字不同…

nodejs多版本随心切换-windows

nodejs多版本控制 1. 安装 nvm github下载地址 不需要卸载已安装的nodejs&#xff0c;安装时会让你选择nodejs的位置&#xff0c;可修改为你已经安装的路径&#xff0c;会自动搜索已安装版本&#xff0c;并进行弹窗询问&#xff0c;选择托管即可 2. 修改配置文件 在 nvm 安装…

全网最适合入门的面向对象编程教程:30 Python的内置数据类型-object根类

全网最适合入门的面向对象编程教程&#xff1a;30 Python 的内置数据类型-object 根类 摘要&#xff1a; 在 Python 中&#xff0c;所有的类都直接或间接继承自一个根类&#xff0c;这个根类是Object。Object类是 Python 中所有新式类的基础类&#xff0c;在 Python 的类层次结…

Docker安装Nacos及动态配置

文章目录 1.安装Nacos1.拉取镜像2.启动Nacos3.开启8848和9848端口1.88482.9848 4.访问nacos1.网址 http://guest:8848/nacos/ 2.Nacos动态配置&#xff08;无法实现bean动态加载&#xff09;1.新建一个配置&#xff0c;使其成为动态的2.引入Nacos依赖3.application.yml配置Naco…

常见病症之中医药草马齿苋

常见病症之中医药草马齿苋 1. 源由2. 马齿苋植物描述药用部分主要成分药理作用使用方法注意事项 2. 常用方剂2.1 马齿苋汤2.2 马齿苋粥 3. 马齿苋的奇效具体应用实例 4. 湿疹方剂4.1 常见方剂内服方剂加减调整外用方剂 4.2 加“马齿苋”内服方剂加减调整外用方剂 4.3 注意事项 …

【Spring Boot】配置 Spring Security

配置 Spring Security 1.继承 WebSecurityConfigurerAdapter2.配置自定义策略3.配置加密方式3.1 BCrypt 加密 4.自定义加密规则5.配置多用户系统5.1 构建 UserDetailsService 用户信息服务接口5.2 进行安全配置 6.获取当前登录用户信息的几种方式6.1 在 Thymeleaf 视图中获取6.…

第23集《大佛顶首楞严经》

请大家打开讲义第五十二页&#xff0c;癸八&#xff0c;约外道世谛对简显见性非因缘自然。 本经的修学特色&#xff0c;简单地讲&#xff0c;它是在处理生命的根本问题。就是当我们在行菩萨道的时候&#xff0c;我们会去布施、持戒、忍辱或者是禅定&#xff0c;在整个修学当中…

centos 8.5时间设置

编辑 chrony 配置文件 vim /etc/chrony.conf新增内容&#xff1a; server 210.72.145.44 iburst server ntp.aliyun.com iburst同时要注释一下&#xff1a;# pool 2.centos.pool.ntp.org iburst 重启chronydf服务 systemctl restart chronyd.service设置 chronyd 开机自启…

谷粒商城实战笔记-118-全文检索-ElasticSearch-进阶-aggregations聚合分析

文章目录 一&#xff0c;基本概念主要聚合类型 二&#xff0c;实战1&#xff0c;搜索 address 中包含 mill 的所有人的年龄分布以及平均年龄&#xff0c;但不显示这些人的详情2&#xff0c;按照年龄聚合&#xff0c;并且请求每个年龄的平均薪资 Elasticsearch 的聚合&#xff0…

大屏宁德烟草第二版总结,批量导入

toFixed toFixed(x) 方法返回一个表示 numObj 的字符串&#xff0c;如果不该x&#xff0c;会进行四舍五入。 includes() includes() 方法用来判断一个数组是否包含一个指定的值&#xff0c;根据情况&#xff0c;如果包含则返回 true&#xff0c;否则返回 false。 批量导入…