【问题标题】:Preventing implicit conversion of some arguments in a templated member function防止模板化成员函数中某些参数的隐式转换
【发布时间】:2015-07-24 15:50:21
【问题描述】:

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

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

【问题讨论】:

  • 我试图复制你的问题,但对我来说 GCC 4.8.4 和 VS2010 都正常运行。
  • const T&amp; 重载绝对应该优先于 0,即使您没有指定 &lt;int&gt;。我无法在任何编译器上重现。
  • 按预期工作here

标签: c++ templates overloading implicit explicit


【解决方案1】:

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

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

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

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

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


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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-09
    相关资源
    最近更新 更多