При перегрузке операторов в C ++, почему T * предпочтительнее, чем bool? - PullRequest
5 голосов
/ 07 ноября 2019

У меня есть класс-оболочка, который должен вести себя как указатель. Я перегружен operator T* и operator bool. Bool делает дополнительную проверку. Я попытался использовать объект внутри if, но заметил, что вызывается operator T*, а не bool. Может кто-нибудь объяснить мне, почему? Это как-то указано в стандарте? Я тестировал приведенный ниже пример кода в MSVC, clang и gcc, и все они вызывают operator T*. Кроме того, из того, что я прочитал на этой странице (https://en.cppreference.com/w/cpp/language/implicit_conversion), if, следует попытаться привести к bool.

#include <stdio.h>

class MyClass
{
public:
    MyClass(int i)
        : m(i)
    {}

    operator bool() const
    {
        printf("operator bool()\n");
        return m;
    }

    operator int* ()
    {
        printf("operator int* ()\n");
        return &m;
    }

private:
    int m;
};

int main()
{
    MyClass a(5);
    MyClass b(0);

    if (a)
        printf("a is true\n");
    else
        printf("a is false\n");

    if (b)
        printf("b is true\n");
    else
        printf("b is false\n");

    return 0;
}

PS: я также пробовал с !! и (bool),но он по-прежнему вызывает operator int*(). Для operator bool() я должен вызвать его явно.

Ответы [ 3 ]

7 голосов
/ 07 ноября 2019

В вашем определении класса оператор преобразования operator bool объявлен с квалификатором const, но объекты, используемые в операторах if, не являются константными объектами.

operator bool() const
                ^^^^^
{
    printf("operator bool()\n");
    return m;
}

Удалите классификатор const, и будет вызван оператор operator bool.

Или объявите оператор преобразования operator int * как

operator const int* () const
{
    printf("operator int* ()\n");
    return &m;
}

иснова будет вызван оператор operator bool.

Когда оператор имеет квалификатор const и применяется к непостоянному объекту, требуется еще одно преобразование, которое является преобразованием квалификации.

Более тогоВы можете объявить оператор даже как явный. Например

explicit operator bool() 
{
    printf("operator bool()\n");
    return m;
}
2 голосов
/ 07 ноября 2019

Если вы хотите увидеть, как получить правильный ответ Влада (правильный), процесс будет примерно

  1. if утверждение

    Условие является выражением, которое контекстуально преобразуется в bool

  2. Контекстные преобразования подпадают под неявные преобразования - обратите внимание, в частности, что

    Если имеется несколько перегрузок вызываемой функции или оператора, после построения последовательности неявного преобразования из T1 в каждый доступный T2 правила разрешения перегрузки определяют, какая перегрузка компилируется.

    И затем в Порядок преобразований , что третий шаг «ноль или одна стандартная последовательность преобразования» идет после пользовательского преобразования, и что этот шаг может преобразовать указатель в bool.

    Это означает, что обаОпределяемые пользователем операторы преобразования являются жизнеспособными для среднего шага в этой последовательности. Наконец,

  3. Разрешение перегрузки

    описывает, как выбрать жизнеспособную функцию best . Поскольку оба оператора являются жизнеспособными в контексте среднего шага последовательности преобразования, дополнительное преобразование указателя в bool, которое происходит после , не способствует ранжированию перегрузки.

    В частности, ранжирование основано на том факте, что одному оператору требуется постоянная квалификация его неявного первого (this) параметра, а другому - нет. Вот почему пара константных и неконстантных перегрузок одного и того же оператора всегда будет выбирать перегрузку, квалификация которой наиболее точно соответствует объекту, для которого она вызывается.

0 голосов
/ 07 ноября 2019

Я думаю, вы можете найти конкретную формулировку в стандарте. Или это предложение

Но я бы сказал, что вы хотите explicit operator bool()

...