简体   繁体   English

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

[英]Preventing implicit conversion of some arguments in a templated member function

Currently I have a member function defined as such: 目前我有一个成员函数定义如下:

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

With an overload for pointers. 指针过载。

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

I would like to be able to use this function as such: 我希望能够使用这个功能:

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

This way I can have a parameter object that either owns the data that it represents, or points to a user owned member. 这样我可以拥有一个参数对象,该对象拥有它所代表的数据,或者指向用户拥有的成员。

Now the problem that I have is with the current setup MSVC implicitly will convert the const 0 of "name" to a pointer, so it ends up calling the overload designed for pointers. 现在我遇到的问题是当前设置MSVC隐式地将“name”的const 0转换为指针,因此它最终调用为指针设计的重载。 I can use the explicit keyword, but then I can't get the implicit conversion from const char[] to std::string for the name parameter. 我可以使用explicit关键字,但是我无法从name char []到std :: string的name参数进行隐式转换。 Is there a way of telling the compiler, MSVC and GCC that a certain field should not be implicitly converted, or at least for it to prefer the const T& version over the T* version? 有没有办法告诉编译器,MSVC和GCC某个字段不应该被隐式转换,或者至少它更喜欢const T&版本而不是T *版本?

This is a VC++ bug. 这是一个VC ++错误。 The first argument's conversion is identical for both overloads ( char const[5] => std::string const& ). 第一个参数的转换对于两个重载都是相同的( char const[5] => std::string const& )。
For the second argument, there are two distinct standard conversion sequences though: For the T const& -overload, the conversion is an identity conversion - §13.3.3.1.4/1: 对于第二个参数,有两个不同的标准转换序列:对于T const& -overload,转换是一个标识转换 - §13.3.3.1.4/ 1:

When a parameter of reference type binds directly (8.5.3) to an argument expression, the implicit conversion sequence is the identity conversion, unless the argument expression has a type that is a derived class of the parameter type […] 当引用类型的参数直接(8.5.3)绑定到参数表达式时,隐式转换序列是标识转换,除非参数表达式的类型是参数类型的派生类[...]

However, converting 0 to a pointer type has Conversion rank. 但是,将0转换为指针类型具有转换等级。 §4.10 goes §4.10去

A null pointer constant is an integer literal (2.13.2) with value zero or a prvalue of type std::nullptr_t . 空指针常量是值为零的整数文字(2.13.2)或类型为std::nullptr_t A null pointer constant can be converted to a pointer type; 空指针常量可以转换为指针类型; the result is the null pointer value of that type and is distinguishable from every other value of object pointer or function pointer type. 结果是该类型的空指针值 ,并且可以与对象指针或函数指针类型的每个其他值区分开。 Such a conversion is called a null pointer conversion . 这种转换称为空指针转换

And §13.3.3.1.1/3 categorizes that accordingly, while also listing our identity conversion and how both relate: §13.3.3.1.1/ 3对此进行了分类,同时也列出了我们的身份转换以及两者如何相关:

在此输入图像描述


The best workaround is to simply upgrade VC++, as recent versions select the correct overload (eg compare with rextester's VC++ ). 最好的解决方法是简单地升级VC ++,因为最新版本选择了正确的重载(例如与rextester的VC ++进行比较)。
Another option is to take data by reference instead for your second overload. 另一种选择是通过引用获取data而不是第二次重载。 Ambiguities would be prevented by §13.3.3.2/3.2.6. §13.3.3.2/ 3.2.6将阻止歧义。 Or simply don't overload updateParameter at all and provide a second function template instead. 或者根本不要重载updateParameter ,而是提供第二个函数模板。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM