Аналогичное преобразование при перегрузке wstring и wchar_t * - PullRequest
1 голос
/ 04 апреля 2011

У меня есть следующий код:

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 * (так?), Так почему эти двусмысленности?

Заранее спасибо

Ответы [ 3 ]

4 голосов
/ 04 апреля 2011

Четвертая перегрузка должна быть перемещена в верхнюю часть списка, чтобы она отображалась первой.

Все первые три перегрузки пытаются вызвать четвертую перегрузку, но она еще не была объявлена, поэтомуне найден при разрешении перегрузки.


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)

Нет никакой двусмысленности для вызова match в (1) , потому что в этот момент видна только одна функция с именем match.

Для вызова match не существует двусмысленности в (2) , потому что (2) лучше соответствует аргументам, чем (1) :

  • Для вызова (2) первый аргумент требует вызова конструктора преобразования std::wstring, а второй аргумент - точное совпадение.

  • Чтобы вызвать (1) , для обоих аргументов необходимо вызвать конструктор преобразования.

Неоднозначностьпроисходит для (3) , поскольку ни одна из трех доступных перегрузок не является «наилучшей»:

  • Для вызова (1) , конструктора преобразованиянужно будет вызвать оба аргумента.

  • Чтобы вызвать (2) , конструктор преобразования должен быть вызван для первого аргумента, а второй аргумент является точным соответствием.

  • Для вызова (3) первый аргумент является точным совпадением, но для второго аргумента должен быть вызван конвертирующий конструктор.

Ни один из этих трех не является однозначно лучше, чем два других.

Если (4) перемещено для объявления до других перегрузок,это будет однозначно лучшее совпадение для вызова, сделанного в (1) , (2) и (3) , поскольку оба аргумента будут точным соответствиемво всех трех случаях.

2 голосов
/ 04 апреля 2011

Да, потому что C ++ использует некоторые конструкторы с 1 параметром в качестве неявных преобразователей.Например, std :: wstring должен иметь конструктор wstring (wchar_t *)

0 голосов
/ 04 апреля 2011

wstring (это просто basic_string <>) имеет ctor с единственным параметром const wchar_t *.Это позволяет неявное преобразование из 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);
    }

   .........
}
...