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

时间:2015-07-24 15:50:22

标签: c++ templates overloading implicit explicit

目前我有一个成员函数定义如下:

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隐式地将“name”的const 0转换为指针,因此它最终调用为指针设计的重载。我可以使用explicit关键字,但是我无法从name char []到std :: string的name参数进行隐式转换。 有没有办法告诉编译器,MSVC和GCC某个字段不应该被隐式转换,或者至少是因为它更喜欢const T&amp;版本超过T *版本?

1 个答案:

答案 0 :(得分:2)

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

  

当引用类型的参数直接绑定(8.5.3)为a时   参数表达式,隐式转换序列是标识   转换,除非参数表达式的类型是a   参数类型[...]

的派生类

但是,将0转换为指针类型具有转换排名。 §4.10去

  

空指针常量是一个整数文字(2.13.2),其值为零   或std::nullptr_t类型的prvalue。空指针常量可以是   转换为指针类型;结果是空指针值   该类型并且可以与对象的每个其他值区分开来   指针或函数指针类型。这样的转换   被称为空指针转换

并且§13.3.3.1.1/ 3相应地对其进行了分类,同时也列出了我们的身份转换以及两者如何相关:

enter image description here

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