目前我有一个成员函数定义如下:
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 *版本?
答案 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相应地对其进行了分类,同时也列出了我们的身份转换以及两者如何相关:
最好的解决方法是简单地升级VC ++,因为最新版本选择了正确的重载(例如与rextester's VC++比较)。
另一种选择是通过引用取data
代替第二次重载。 §13.3.3.2/ 3.2.6将阻止歧义。或者根本不要重载updateParameter
,而是提供第二个功能模板。