青海城乡住房和建设厅网站,中国容桂品牌网站建设,个人搭建网站要多少钱,wordpress 管理权限管理一窥模板的替换和匹配方式#xff1a;偏特化的参数比泛化版本的还要多#xff1a;判断是不是std::pair#xff1c;,#xff1e;。_stdpair模板参数太多-CSDN博客 简介
在一个项目里#xff0c;调用了第三封的库#xff0c;这个库里面有个类用的很多#xff0c;而且其构…一窥模板的替换和匹配方式偏特化的参数比泛化版本的还要多判断是不是std::pair,。_stdpair模板参数太多-CSDN博客 简介
在一个项目里调用了第三封的库这个库里面有个类用的很多而且其构造函数至少有6个并且个人感觉还不够多。根据实际使用还得增加一些。 需求
1、增加构造函数比如除了下面的还增加(ElementId,const std::wstring modelName)以及FarElementId
2、希望能用通用的构造接口来生成对象比如Create
3、希望能用指针对象智能指针 第三方库的6个构造函数
EditElementHandle (MSElementDescrCP descr, bool isUnmodified, DgnModelRefR modelRef);
EditElementHandle() {}
EditElementHandle (MSElementDescrP descr, bool owned, bool isUnmodified, DgnModelRefP modelRefNULL) ;
EditElementHandle (ElementRefP elRef, DgnModelRefP modelRefNULL) : ElementHandle (elRef, modelRef) {}
EditElementHandle (MSElementCP el, DgnModelRefP modelRef) : ElementHandle (el, modelRef){}
EditElementHandle (ElementId id, DgnModelRefP modelRef) : ElementHandle (id, modelRef) {} 定义智能指针
using EditElementHandlePtr std::shared_ptrDgnPlatform::EditElementHandle;
定义工厂EEHFactory
struct EEhFactory
{template typename ... Argsstatic HCHXKERNEL::EditElementHandlePtrCreate(Args ... args){return std::make_sharedDgnPlatform::EditElementHandle(std::forwardArgs(args)...);}
};
可以这样使用
ElementRefP elRef{ NULL };
DgnModelRefP modelRef{ NULL };
auto editElementHandlePtr1 EEhFactory::Create(elRef, modelRef);新需求
我想这样使用怎么办
DgnPlatform::ElementId eid0{ 0 };
std::wstring str{ L };
auto editElementHandlePtr2 EEhFactory::Create(eid0, str);或者
auto editElementHandlePtr3 EEhFactory::Create(eid0, std::wstring{ LPipeDrawing });或者
auto editElementHandlePtr3 EEhFactory::Create(eid0, LPipeDrawing );
问题相当于增加了两个构造函数。这两个函数由我们自己实现
第一个尝试非泛化版本
先加入普通静态函数看什么效果能否达到重载的目的
struct EEhFactory
{template typename ... Argsstatic HCHXKERNEL::EditElementHandlePtrCreate(Args ... args){return std::make_sharedDgnPlatform::EditElementHandle(std::forwardArgs(args)...);}static HCHXKERNEL::EditElementHandlePtrCreate(ElementId eid, const std::wstring modelName)
{DgnModelRefP modelRef NULL;if (!MiscUtil::GetModelRefByName(modelRef, modelName.c_str(), false, false))return NULL;return EEhFactoryXXX::Create(eid, modelRef);
}
};调用
{DgnPlatform::ElementId eid0{ 0 };//, eid1{ 0 };DgnModelRefP modelRef NULL;EEhFactoryXXX::Create(eid0, modelRef);
}
编译结果是 注意最后一句
note: 参见对正在编译的函数 模板 实例化“std::shared_ptr
Bentley::DgnPlatform::EditElementHandleEEhFactoryXXX::CreateBentley::DgnPlatform::ElementId,std::wstring
(Bentley::DgnPlatform::ElementId ,std::wstring )”的引用
明明我们想要调用的是
static HCHXKERNEL::EditElementHandlePtr Create(ElementId eid, const std::wstring modelName);
结果看起来貌似编译器优先去泛型那边了
template typename ... Argsstatic std::shared_ptrDgnPlatform::EditElementHandle/*HCHXKERNEL::EditElementHandlePtr*/Create(Args ... args){return std::make_sharedDgnPlatform::EditElementHandle(std::forwardArgs(args)...);}
这个第26行就是泛型函数里的压根没走到我们的普通函数那里。 第二个尝试泛化版本
改造一下想法是推导的时候
Param1st推导成ElementId而Param2ndst推导成std::wstring
struct EEhFactoryXXX
{template typename ... Argsstatic std::shared_ptrDgnPlatform::EditElementHandle/*HCHXKERNEL::EditElementHandlePtr*/Create(Args ... args){return std::make_sharedDgnPlatform::EditElementHandle(std::forwardArgs(args)...);}templatetypename Tstruct IsFarElementID : std::false_type{};templatestruct IsFarElementIDDgnPlatform::DgnHistory::FarElementID : std::true_type{};templatetypename Tstruct IsElementId : std::false_type{};templatestruct IsElementIdDgnPlatform::ElementId : std::true_type{};templatetypename Tstruct IsWstring : std::false_type{};templatestruct IsWstringstd::wstring : std::true_type{};template typename Param1st, typename Param2ndst,typename std::enable_ifIsElementIdParam1st::value IsWstringParam2ndst::value, int::type 0static HCHXKERNEL::EditElementHandlePtr Create(Param1st eid,const Param2ndst modelName){DgnModelRefP modelRef NULL;if (!MiscUtil::GetModelRefByName(modelRef, modelName.c_str(), false, false))return NULL;//using eid_decayType typename std::decayParam1st::type;//typename std::decayParam1st::type a;//TypeDisplayerdecltype(a) aType;//return NULL;return EEhFactoryXXX::Create(eid, modelRef);}
};调用
{DgnPlatform::ElementId eid0{ 0 };//, eid1{ 0 };std::wstring str{ L };auto editElementHandlePtr2 EEhFactoryXXX::Create(eid0, str);
}
但是呢编译结果让人大吃一惊出现的编译提示和之前一模一样说明压根还是没走到我们新的泛型函数里来。 这次终于引起我的注意了
Param1st推导成Bentley::DgnPlatform::ElementId而Param2ndst推导成std::wstring
至于我期望的Elementid和const std::wstring压根不挨着const跑哪去了压根没搭理我给出的定义
而且还是走的原来的变参的模板定义。
Bentley::DgnPlatform::EditElementHandleEEhFactoryXXX::CreateBentley::DgnPlatform::ElementId,std::wstring
(Bentley::DgnPlatform::ElementId ,std::wstring )”的引用
果然泛型这玩意水太深了。
分析函数重载
睡觉之前琢磨了一下感觉有头绪了
首先类EEHFactory里的两个Create函数都是static的泛型成员变量。一个是最泛化的版本另一个是特化的版本。
这貌似牵扯到函数重载的问题
但看看这个函数模板之间不能重载把类型推导放到形参里就可以了_template 函数无法重载-CSDN博客
是不是要分两种情况是不是存在最泛化的版本。
存在最泛化的版本时
而且当前这个泛化的版本是属于变参的什么类型都能接受的那种。
编译器扫描到存在一个这样的泛化版本先用它解析了一下参数类型。由于它是引用类型Args ... args左值的变量就推导出了左值引用
{DgnPlatform::ElementId eid0{ 0 };std::wstring str{ L };auto editElementHandlePtr2 EEhFactoryXXX::Create(eid0, str);
eid0和str都是左值变量最后推到出来的类型就是左值引用ElementId和std::wstring
}auto editElementHandlePtr2
EEhFactoryXXX::Create(eid0, std::wstring{LPipeDrawing});
的推导结果就是ElementId和std::wstring
好了这个泛化版本先把类型给推导出来了基调给定下来了那就是ElementId和std::wstring。这个时候它发现另一个Create函数貌似可以重载但得先检查一下参数是否匹配。
它发现此Create的参数是Param1st eid和const Param2ndst modelName
从形式上看就不符合。
所以最后还是走最泛化的版本。
template typename Param1st, typename Param2ndst,typename std::enable_ifIsElementIdParam1st::value IsWstringParam2ndst::value, int::type 0static HCHXKERNEL::EditElementHandlePtr Create(Param1st eid,const Param2ndst modelName){DgnModelRefP modelRef NULL;if (!MiscUtil::GetModelRefByName(modelRef, modelName.c_str(), false, false))return NULL;return EEhFactoryXXX::Create(eid, modelRef);}
那我就让你如意重新定义一下
把Param1st eid和const Param2ndst modelName改成
Param1st eid和Param2ndst modelName。
就没事了。
struct EEhFactoryXXX
{template typename ... Argsstatic std::shared_ptrDgnPlatform::EditElementHandle/*HCHXKERNEL::EditElementHandlePtr*/Create(Args ... args){return std::make_sharedDgnPlatform::EditElementHandle(std::forwardArgs(args)...);}templatetypename Tstruct IsFarElementID : std::false_type{};templatestruct IsFarElementIDDgnPlatform::DgnHistory::FarElementID : std::true_type{};templatetypename Tstruct IsElementId : std::false_type{};templatestruct IsElementIdDgnPlatform::ElementId : std::true_type{};templatetypename Tstruct IsWstring : std::false_type{};templatestruct IsWstringstd::wstring : std::true_type{};template typename Param1st, typename Param2ndst,typename std::enable_ifIsElementIdParam1st::value IsWstringParam2ndst::value, int::type 0static HCHXKERNEL::EditElementHandlePtr Create(Param1st eid,Param2ndst modelName){DgnModelRefP modelRef NULL;if (!MiscUtil::GetModelRefByName(modelRef, modelName.c_str(), false, false))return NULL;return EEhFactoryXXX::Create(eid, modelRef);}
};调用
{DgnPlatform::ElementId eid0{ 0 };//, eid1{ 0 };std::wstring str{ L };auto editElementHandlePtr2 EEhFactoryXXX::Create(eid0, str);
} 下面这个例子帮助理解但这是个类的例子函数可能有所不同但仅仅是帮助理解。
A的泛化版本根本没有实现但它是不能缺少的否则就编译报错。
第二个A是个偏特化版本。还是特化 enable_if和类的偏特化-CSDN博客
#include iostream
templateclass T, class Enabledvoid
class A;templateclass T
class AT, typename std::enable_ifstd::is_floating_pointT::value::type {
public:A() { std::cout partial specialization\r\n;}
}; // specialization for floating point typesint main() {Adouble a;
} 不存在最泛化版本时
编译器别无选择。可以编译成功。
但如果是类必须要有最泛化的版本。
struct EEhFactoryXXX
{///code{.unparsed}///此函数的功能/// 创建EditElementHandle的指针对象/// 最泛化的版本///endcode ///return true:成功 false:失败///author Simon.Zou date 2024/02/20//template typename ... Args//static std::shared_ptrDgnPlatform::EditElementHandle/*HCHXKERNEL::EditElementHandlePtr*/// Create(Args ... args)//{// return std::make_sharedDgnPlatform::EditElementHandle(std::forwardArgs(args)...);//}templatetypename Tstruct IsFarElementID : std::false_type{};templatestruct IsFarElementIDDgnPlatform::DgnHistory::FarElementID : std::true_type{};templatetypename Tstruct IsElementId : std::false_type{};templatestruct IsElementIdDgnPlatform::ElementId : std::true_type{};templatetypename Tstruct IsWstring : std::false_type{};templatestruct IsWstringstd::wstring : std::true_type{};template typename Param1st, typename Param2ndst,typename std::enable_ifIsElementIdParam1st::value IsWstringParam2ndst::value, int::type 0static HCHXKERNEL::EditElementHandlePtr Create(Param1st eid,Param2ndst modelName){DgnModelRefP modelRef NULL;if (!MiscUtil::GetModelRefByName(modelRef, modelName.c_str(), false, false))return NULL;return NULL; //return EEhFactoryXXX::Create(eid, modelRef);
//暂时切换成return NULL。因为没有函数接收ElementId和DgnModelRefp}
//
// template
// typename Param1st, typename Param2ndst,
// typename std::enable_if
// IsElementIdParam1st::value
// IsWstringParam2ndst::value
// , int::type 0
//
// static HCHXKERNEL::EditElementHandlePtr Create(
// Param1st eid,
// Param2ndst modelName
// )
// {
// return EEhFactoryXXX::Create(eid, modelName);
// }};测试
DgnPlatform::ElementId eid0{ 0 };//, eid1{ 0 };
std::wstring str{ L };
auto editElementHandlePtr2 EEhFactoryXXX::Create(eid0, str);