防止模板化成员函数中某些参数的隐式转换
Preventing implicit conversion of some arguments in a templated member function
目前我有一个这样定义的成员函数:
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 关键字,但是我无法将名称参数从 const char[] 隐式转换为 std::string。
有没有办法告诉编译器、MSVC 和 GCC 某个字段不应该被隐式转换,或者至少让它更喜欢 const T& 版本而不是 T* 版本?
这是一个 VC++ 错误。两个重载的第一个参数的转换是相同的 (char const[5]
=> std::string const&
).
对于第二个参数,虽然有两个不同的标准转换序列:对于 T const&
-重载,转换是身份转换 - §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 […]
但是,将0
转换为指针类型具有转换等级。 §4.10 去
A null pointer constant is an integer literal (2.13.2) with value zero
or a prvalue of type 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.
§13.3.3.1.1/3 对此进行了相应的分类,同时还列出了我们的身份转换以及两者之间的关系:
最好的解决方法是简单地升级 VC++,因为最新版本 select 是正确的重载(例如与 rextester's VC++ 进行比较)。
另一种选择是通过引用取 data
而不是第二次重载。 §13.3.3.2/3.2.6 可以避免歧义。或者根本不重载 updateParameter
而是提供第二个函数模板。
目前我有一个这样定义的成员函数:
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 关键字,但是我无法将名称参数从 const char[] 隐式转换为 std::string。 有没有办法告诉编译器、MSVC 和 GCC 某个字段不应该被隐式转换,或者至少让它更喜欢 const T& 版本而不是 T* 版本?
这是一个 VC++ 错误。两个重载的第一个参数的转换是相同的 (char const[5]
=> std::string const&
).
对于第二个参数,虽然有两个不同的标准转换序列:对于 T const&
-重载,转换是身份转换 - §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 […]
但是,将0
转换为指针类型具有转换等级。 §4.10 去
A null pointer constant is an integer literal (2.13.2) with value zero or a prvalue of type
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.
§13.3.3.1.1/3 对此进行了相应的分类,同时还列出了我们的身份转换以及两者之间的关系:
最好的解决方法是简单地升级 VC++,因为最新版本 select 是正确的重载(例如与 rextester's VC++ 进行比较)。
另一种选择是通过引用取 data
而不是第二次重载。 §13.3.3.2/3.2.6 可以避免歧义。或者根本不重载 updateParameter
而是提供第二个函数模板。