3

Если у меня есть struct A определяется как:C++ оператор == и неявное разрешение

struct A { 
    const char *data; 
    operator const char *() const { return data; } 
    friend bool operator== (const A &s1, const char *s2) 
    { return /* typical string comparison result */; } 
}; 

И я пишу A{"hello"} == "test2", это A::operator== называется? Что в стандарте гласит, что (и почему не A неявно преобразован в const char *?)

А что насчет "test2" == A{"hello"}? Преобразуется ли в этом случае A?

EDIT: Что если struct A также член:

friend bool operator== (const char *s1, const A &s2) 
+0

просто используйте std :: string – Davidbrcz

+0

@Davidbrcz Это совсем не то, о чем этот вопрос. –

+0

Я думал, что 'friend' делает функцию ** non ** - member (т. Е. Глобальную). –

ответ

4

Когда вы

A{"hello"} == "test2" 

произведем разрешение перегрузки на operator==. Во-первых, мы находим жизнеспособные кандидатов ([over.match.viable]), через поиск имен:

operator==(A const&, const char*); // yours 
operator==(const char*, const char*); // built-in 

Далее мы определяем, какой кандидат имеет лучшую неявное последовательность преобразования. Это первый тай-брейк в [over.match.best]:

Учитывая эти определения, жизнеспособный функция F1 определяется быть лучше функцией, чем другая жизнеспособной функция F2, если для всех аргументов я, ИКС я (F1), не хуже, последовательность преобразования, чем ICS я (F2), а затем
(1.3) - для некоторого аргумента J, ИКС J (F1) является лучшей последовательностью преобразования, чем ICS J (F2), или, если не то, что [...]

Оба оператора являются Четк.совп на 2-й аргумент. По первому аргументу ваш operator== - это точное соответствие, тогда как для встроенного пользователя требуется определенное пользователем преобразование. Точное совпадение - лучший вид конверсии, а определяемый пользователем худший - следовательно, у вас есть лучшая последовательность преобразования и становится лучшей жизнеспособной функцией.

В более общих терминах A неявно преобразован в const char*, потому что есть лучший вариант, где это не обязательно.


Когда вы делаете:

"test2" == A{"hello"}; 

Ваш кандидат не является жизнеспособным - нет неявного преобразования из const char* в A const& (первый аргумент), поэтому единственный реальный кандидатом является встроенным в сравнении для const char*, для которого требуется пользовательское преобразование от A до const char*.

Если вы хотите, чтобы ваш A::operator== был использован, то вам необходимо добавить новую перегрузку для operator==(const char*, A const&).

+0

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

+0

Просто, чтобы быть ясным: во втором случае, если бы у меня был A :: A (const char * s) {} ', то эффективно' A ("test") == A {"hello"} 'будет вызываться? или требуется ли это неявное преобразование? – Olivetree

+0

@ GillBates Да, я был, поэтому я мог знать обо всех других случаях, о которых я не думал сейчас. Я думаю, что они будут придерживаться одного и того же правила. Может быть, я должен уточнить вопрос? – Olivetree

Смежные вопросы