防止在模板成员函数中隐式转换某些参数

丹尼尔·穆迪(Daniel Moodie)

目前,我有一个这样定义的成员函数:

template<typename T> bool updateParameter(const std::string& name, const T& data);

具有指针的重载。

template<typename T> bool updateParameter(const std::string& name, T* data);

我希望能够像这样使用此功能:

int test = 20;
updateParameter<int>("name", 0);
updateParameter<int>("Referenced parameter", &test);

这样,我就可以拥有一个参数对象,该对象要么拥有它所代表的数据,要么指向一个用户拥有的成员。

现在,我的问题是当前设置MSVC隐式将“名称”的const 0转换为指针,因此最终调用了为指针设计的重载。我可以使用显式关键字,但是对于名称参数,我无法从const char []隐式转换为std :: string。有没有办法告诉编译器,MSVC和GCC某个字段不应该隐式转换,或者至少让它更喜欢const T&版本而不是T *版本?

哥伦布

这是一个VC ++错误。对于两个重载(char const[5]=> std::string const&,第一个参数的转换都是相同的
对于第二个参数,虽然有两个不同的标准转换序列:对于T const&-overload,该转换是一个身份转换-§13.3.3.1.4/ 1:

当引用类型的参数直接绑定(8.5.3)到参数表达式时,隐式转换序列是恒等转换,除非参数表达式的类型是参数类型[…]的派生类。

但是,转换0为指针类型具有转换等级。第4.10条

空指针常数是整数字面(2.13.2)与零值或类型的prvalue std::nullptr_t空指针常量可以转换为指针类型。结果是该类型空指针值,并且可以与对象指针或函数指针类型的所有其他值区分开。这种转换称为空指针转换

§13.3.3.1.1/ 3对此进行了相应的分类,同时还列出了我们的身份转换以及两者之间的关系:

在此处输入图片说明


最好的解决方法是简单地升级VC ++,因为最新版本会选择正确的过载(例如,与rextester的VC ++比较)。
另一个选择是data通过引用代替第二次重载。§13.3.3.2/ 3.2.6可以防止歧义。或者根本不重载updateParameter,而是提供第二个功能模板。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章