Подтвердить что ты не робот

Bool vs void * бросает на тот же объект

Приведенный ниже код печатает "оператор bool" при использовании в инструкции if и "operator void *", когда ему нужен вызов bool для вызова функции.

Почему он не использует operator bool для вызова функции? И как его использовать в обоих случаях?

#include <iostream>

class A
{
public:
    explicit operator bool() const
    {
        std::cout << "operator bool" << std::endl;
        return true;
    }

    operator void*() const
    {
        std::cout << "operator void*" << std::endl;
        return 0;
    }
};

void f(bool valid)
{
    std::cout << "f called " << valid << std::endl;
}

int main(int argc, char *argv[])
{
    A a;

    if(a)
        std::cout << "if a" << std::endl;

    f(a);

    return 0;
}
4b9b3361

Ответ 1

В операторе if рассматриваются неявные и явные операторы преобразования. Поскольку A имеет operator bool, он выбирает этот, поскольку он лучше соответствует преобразованию A в void*, а затем преобразует его в bool.

Но в любом другом утверждении, которое не является условиями (if, while,...), явные операторы преобразования не участвуют в разрешении перегрузки, а единственным действительным оператором тогда является operator void*, что может использоваться, потому что существует неявное преобразование из указателей в bool.

Если вы хотите, чтобы operator bool был выбран, вам нужно сделать его не explicit или использовать приведение (потому что это означает, что его обозначение explicit означает, что нужно явно использовать его)

f(static_cast<bool>(a));

Ответ 2

Причина в том, что оператор объявлен с помощью спецификатора функции explicit.

В условии оператора if значение контекстуально преобразуется в тип bool.

Из стандарта С++ (4 стандартных преобразования)

2 [Примечание: выражения с заданным типом будут неявно преобразованы для других типов в нескольких контекстах:

...

- При использовании в условии оператора if или итерации (6.4, 6.5). Тип назначения - bool.

Однако, когда значение передается функции в качестве аргумента, используется так называемая инициализация копирования. В этом случае спецификатор спецификации явно запрещает преобразование в тип bool.

Из стандарта С++ (функции преобразования 12.3.2)

2 Функция преобразования может быть явной (7.1.2), и в этом случае она рассматривается только как пользовательское преобразование для прямой инициализации(8.5). В противном случае определяемые пользователем преобразования не ограничиваются в назначениях и инициализациях.

Простым способом принудительного вызова оператора bool является

f( bool( a ) );