【问题标题】:Similar conversion in overloading wstring and wchar_t *重载 wstring 和 wchar_t 中的类似转换 *
【发布时间】:2011-07-29 08:20:59
【问题描述】:

我有以下代码:

inline bool match(const std::wstring & text1, const std::wstring & text2)
{
    return match(text1.c_str(), text2.c_str());
}

inline bool match(const std::wstring & text1, const wchar_t * text2)
{
    return match(text1.c_str(), text2);
}

inline bool match(const wchar_t * text1, const std::wstring & text2)
{
    return match(text1, text2.c_str());
}

inline bool match(const wchar_t * text1, const wchar_t * text2)
{
    return !wcscmp(text1, text2);
}

我得到了:

error C2666: 'match' : 3 overloads have similar conversions
1>   could be 'bool match(const wchar_t *,const std::wstring &)'
1>   or       'bool match(const std::wstring &,const wchar_t *)'
1>   or       'bool match(const std::wstring &,const std::wstring &)'

wstring 和 wchar_t * 之间不应该有任何隐式转换(应该吗?),那么为什么会有这些歧义呢?

提前谢谢你

【问题讨论】:

    标签: c++ overloading implicit-conversion wchar-t wstring


    【解决方案1】:

    需要将第四个重载移到列表顶部,以便它首先出现。

    前三个重载都尝试调用第四个重载,但是还没有被声明,所以在重载解析时找不到。


    std::wstring 确实有一个转换构造函数,它允许将const wchar_t* 隐式转换为std::wstring。这是造成歧义的部分原因,尽管真正的问题是重载的顺序。

    虽然在前三个重载中对match 的任何调用都不会调用第四个重载,但在第三个重载中的调用只有一个模糊性。原因如下:

    inline bool match(const std::wstring & text1, const std::wstring & text2) // (1)
    inline bool match(const std::wstring & text1, const wchar_t * text2)      // (2)
    inline bool match(const wchar_t * text1, const std::wstring & text2)      // (3)
    inline bool match(const wchar_t * text1, const wchar_t * text2)           // (4)
    

    (1) 中对match 的调用没有歧义,因为此时只有一个名为match 的函数可见。

    (2) 中对 match 的调用没有歧义,因为 (2)(1) 更适合参数匹配

    • 要调用 (2),第一个参数需要调用 std::wstring 转换构造函数,而第二个参数是完全匹配的。

    • 要调用 (1),需要为两个参数调用转换构造函数。

    (3) 出现歧义,因为三个可用的重载都不是“最佳”:

    • 要调用 (1),需要为两个参数调用转换构造函数。

    • 要调用 (2),需要为第一个参数调用转换构造函数,并且第二个参数完全匹配。

    • 要调用 (3),第一个参数是完全匹配的,但需要为第二个参数调用转换构造函数。

    这三个都没有比其他两个更好。

    如果将 (4) 移动到在其他重载之前声明,那么它无疑会更好地匹配 (1) 中的调用(2)(3),因为这两个参数在所有三种情况下都是完全匹配的。

    【讨论】:

      【解决方案2】:

      有,因为 C++ 使用一些 1 参数构造函数作为隐式转换器。例如,std::wstring 必须有 wstring(wchar_t*) 构造函数

      【讨论】:

      • 呃。制作字符串的新副本,只是为了不想要的类型转换,似乎违背了 C++ 的精神。
      【解决方案3】:

      wstring(它只是一个 basic_string)具有带有单个 const wchar_t* 参数的 ctor。这可以实现从 const wchar_t* 到 wstring 的隐式转换。从头文件中,

      typedef basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> > wstring;
      
      // TEMPLATE CLASS basic_string
      template<class _Elem, class _Traits, class _Ax> 
          class basic_string : public _String_val<_Elem, _Ax>
      {
             .........
      
          basic_string(const _Elem *_Ptr) : _Mybase()
          {   // construct from [_Ptr, <null>)
              _Tidy();
              assign(_Ptr);
          }
      
         .........
      }
      

      【讨论】:

        猜你喜欢
        • 2015-09-16
        • 1970-01-01
        • 2012-02-13
        • 2017-12-12
        • 2013-07-28
        • 1970-01-01
        • 1970-01-01
        • 2011-05-20
        • 2020-03-21
        相关资源
        最近更新 更多