Qual é o significado de “operador bool () const”


Respostas:


145

Funções de membro do formulário

operator TypeName()

são operadores de conversão. Eles permitem que objetos do tipo de classe sejam usados ​​como se fossem do tipo TypeNamee, quando o são, são convertidos para TypeNameusar a função de conversão.

Nesse caso específico, operator bool()permite que um objeto do tipo de classe seja usado como se fosse um bool. Por exemplo, se você tiver um objeto do tipo de classe chamado obj, você pode usá-lo como

if (obj)

Isso chamará o operator bool(), retornará o resultado e usará o resultado como a condição do if.

Deve-se notar que operator bool()é uma ideia muito ruim e você realmente nunca deve usá-la. Para uma explicação detalhada de por que isso é ruim e para a solução do problema, consulte "The Safe Bool Idiom".

(C ++ 0x, a próxima revisão do Padrão C ++, adiciona suporte para operadores de conversão explícitos. Eles permitirão que você escreva um cofre explicit operator bool()que funcione corretamente sem ter que pular para implementar o Idiom Bool Seguro.)


1
"usado como se fosse um bool" implica falsamente que você poderia, digamos, atribuir a ele um valor booleano. Em vez disso, no código do postador, ele gera uma variável temporária do tipo bool que se relaciona ao valor momentâneo de col, mas é, a partir daí, independente do objeto que a criou. Além disso, a menção do Safe Bool Idiom é ótima, mas apenas para registrar que existem pontos de vista contrários: IMHO, o conselho "nunca use realmente" é exagerado - ele fornece verificações do compilador mais rígidas contra o uso indevido ao custo de uma API mais ofuscada que pode levar ao uso indevido acidental.
Tony Delroy

1
@Tony: Bem, pode ser usado como se fosse um bool; já que o resultado da conversão é um rvalue ( bool), não, você não pode atribuir a ele. Se fosse um lvalue modificável (por exemplo bool&), você poderia atribuí-lo. Quanto à correção, argumento que an operator bool()é sempre incorreto porque permite o uso de um objeto do tipo classe em um grande número de situações em que você nunca quer que ele seja usado. Safe Bool é uma alternativa muito superior.
James McNellis

1
Portanto, de acordo com o último parágrafo, hoje é perfeitamente normal usar explicit operator bool(). Eu compreendo corretamente?
Zingam

1
O comitê C ++ parece discordar de você no operador bool (). Pelo menos para a versão mais recente do padrão (por exemplo, en.cppreference.com/w/cpp/utility/optional ). Ou talvez você quisesse dizer que apenas o código STL deveria ter permissão para usar isso?
Joe Steele,

2
@JoeSteele - Consulte stackoverflow.com/a/16615725/2492801 . Os operadores de conversão explícita são seguros!
Benjamin Bihler

9
operator bool() const 
{
    return col != 0;
}

Define como a classe pode ser convertida em um valor booleano, o constdepois que ()é usado para indicar que este método não sofre mutação (altera os membros desta classe).

Você normalmente usaria esses operadores da seguinte maneira:

airplaysdk sdkInstance;
if (sdkInstance) {
    std::cout << "Instance is active" << std::endl;
} else {
    std::cout << "Instance is in-active error!" << std::endl;
}

7

Eu gostaria de dar mais códigos para deixar isso claro.

struct A
{
    operator bool() const { return true; }
};

struct B
{
    explicit operator bool() const { return true; }
};

int main()
{
    A a1;
    if (a1) cout << "true" << endl; // OK: A::operator bool()
    bool na1 = a1; // OK: copy-initialization selects A::operator bool()
    bool na2 = static_cast<bool>(a1); // OK: static_cast performs direct-initialization

    B b1;     
    if (b1) cout << "true" << endl; // OK: B::operator bool()
    // bool nb1 = b1; // error: copy-initialization does not consider B::operator bool()
    bool nb2 = static_cast<bool>(b1); // OK: static_cast performs direct-initialization
}

3

É uma implicitfunção de conversão definida pelo usuário para converter sua classe em trueou false.

//usage
bool value = yourclassinstance; //yourclassinstance is converted into bool!

1

É uma conversão implícita para bool. Ou seja, sempre que conversões implícitas são permitidas, sua classe pode ser convertida boolchamando esse método.


1

Como os outros já disseram, é para conversão de tipo, neste caso para a bool. Por exemplo:

class A {
    bool isItSafe;

public:
    operator bool() const
    {
        return isItSafe;
    }

    ...
};

Agora posso usar um objeto desta classe como se fosse um booleano:

A a;
...
if (a) {
    ....
}

1

Ao escrever meu próprio unique_ptr, encontrei este caso. Dado std::unique_ptréoperator== :

template<class T1, class D1, class T2, class D2>
bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);

template <class T, class D>
bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;

template <class T, class D>
bool operator==(nullptr_t, const unique_ptr<T, D>& x) noexcept;

E este caso de teste de libstdcxx :

  std::unique_ptr<int> ptr;
  if (ptr == 0)
    { }
  if (0 == ptr)
    { }
  if (ptr != 0)
    { }
  if (0 != ptr)
    { }

Observe porque ptrtem um explicit operator bool() const noexcept;, então operator overload resolutionfunciona bem aqui, por exemplo, ptr == 0escolhe

 template <class T, class D>
 bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;`.

Se não houver nenhuma explicitpalavra-chave aqui, ptrin ptr == 0será convertido em bool, então boolserá convertido em int, porque bool operator==(int, int)está integrado e 0é int. O que está esperando por nós é um erro ambíguo de resolução de sobrecarga.

Aqui está um exemplo mínimo, completo e verificável :

#include <cstddef>
struct A
{
    constexpr A(std::nullptr_t) {}
    operator bool() 
    {
        return true;
    }
};

constexpr bool operator ==(A, A) noexcept
{
    return true;
}

constexpr bool operator ==(A, std::nullptr_t) noexcept
{
    return true;
}

constexpr bool operator ==(std::nullptr_t, A) noexcept
{
    return true;
}

int main()
{
    A a1(nullptr);
    A a2(0);
    a1 == 0;
}

gcc :

prog.cc: In function 'int main()':
prog.cc:30:8: error: ambiguous overload for 'operator==' (operand types are 'A' and 'int')
   30 |     a1 == 0;
      |     ~~ ^~ ~
      |     |     |
      |     A     int
prog.cc:30:8: note: candidate: 'operator==(int, int)' <built-in>
   30 |     a1 == 0;
      |     ~~~^~~~
prog.cc:11:16: note: candidate: 'constexpr bool operator==(A, A)'
   11 | constexpr bool operator ==(A, A) noexcept
      |                ^~~~~~~~
prog.cc:16:16: note: candidate: 'constexpr bool operator==(A, std::nullptr_t)'
   16 | constexpr bool operator ==(A, std::nullptr_t) noexcept
      |                ^~~~~~~~

clang :

prog.cc:30:8: error: use of overloaded operator '==' is ambiguous (with operand types 'A' and 'int')
    a1 == 0;
    ~~ ^  ~
prog.cc:16:16: note: candidate function
constexpr bool operator ==(A, std::nullptr_t) noexcept
               ^
prog.cc:11:16: note: candidate function
constexpr bool operator ==(A, A) noexcept
               ^
prog.cc:30:8: note: built-in candidate operator==(int, int)
    a1 == 0;
       ^
prog.cc:30:8: note: built-in candidate operator==(float, int)
prog.cc:30:8: note: built-in candidate operator==(double, int)
prog.cc:30:8: note: built-in candidate operator==(long double, int)
prog.cc:30:8: note: built-in candidate operator==(__float128, int)
prog.cc:30:8: note: built-in candidate operator==(int, float)
prog.cc:30:8: note: built-in candidate operator==(int, double)
prog.cc:30:8: note: built-in candidate operator==(int, long double)
prog.cc:30:8: note: built-in candidate operator==(int, __float128)
prog.cc:30:8: note: built-in candidate operator==(int, long)
prog.cc:30:8: note: built-in candidate operator==(int, long long)
prog.cc:30:8: note: built-in candidate operator==(int, __int128)
prog.cc:30:8: note: built-in candidate operator==(int, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(int, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(int, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(int, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(long, int)
prog.cc:30:8: note: built-in candidate operator==(long long, int)
prog.cc:30:8: note: built-in candidate operator==(__int128, int)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, int)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, int)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, int)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, int)
prog.cc:30:8: note: built-in candidate operator==(float, float)
prog.cc:30:8: note: built-in candidate operator==(float, double)
prog.cc:30:8: note: built-in candidate operator==(float, long double)
prog.cc:30:8: note: built-in candidate operator==(float, __float128)
prog.cc:30:8: note: built-in candidate operator==(float, long)
prog.cc:30:8: note: built-in candidate operator==(float, long long)
prog.cc:30:8: note: built-in candidate operator==(float, __int128)
prog.cc:30:8: note: built-in candidate operator==(float, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(float, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(float, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(float, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(double, float)
prog.cc:30:8: note: built-in candidate operator==(double, double)
prog.cc:30:8: note: built-in candidate operator==(double, long double)
prog.cc:30:8: note: built-in candidate operator==(double, __float128)
prog.cc:30:8: note: built-in candidate operator==(double, long)
prog.cc:30:8: note: built-in candidate operator==(double, long long)
prog.cc:30:8: note: built-in candidate operator==(double, __int128)
prog.cc:30:8: note: built-in candidate operator==(double, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(double, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(double, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(double, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(long double, float)
prog.cc:30:8: note: built-in candidate operator==(long double, double)
prog.cc:30:8: note: built-in candidate operator==(long double, long double)
prog.cc:30:8: note: built-in candidate operator==(long double, __float128)
prog.cc:30:8: note: built-in candidate operator==(long double, long)
prog.cc:30:8: note: built-in candidate operator==(long double, long long)
prog.cc:30:8: note: built-in candidate operator==(long double, __int128)
prog.cc:30:8: note: built-in candidate operator==(long double, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(long double, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(long double, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(long double, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(__float128, float)
prog.cc:30:8: note: built-in candidate operator==(__float128, double)
prog.cc:30:8: note: built-in candidate operator==(__float128, long double)
prog.cc:30:8: note: built-in candidate operator==(__float128, __float128)
prog.cc:30:8: note: built-in candidate operator==(__float128, long)
prog.cc:30:8: note: built-in candidate operator==(__float128, long long)
prog.cc:30:8: note: built-in candidate operator==(__float128, __int128)
prog.cc:30:8: note: built-in candidate operator==(__float128, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(__float128, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(__float128, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(__float128, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(long, float)
prog.cc:30:8: note: built-in candidate operator==(long, double)
prog.cc:30:8: note: built-in candidate operator==(long, long double)
prog.cc:30:8: note: built-in candidate operator==(long, __float128)
prog.cc:30:8: note: built-in candidate operator==(long, long)
prog.cc:30:8: note: built-in candidate operator==(long, long long)
prog.cc:30:8: note: built-in candidate operator==(long, __int128)
prog.cc:30:8: note: built-in candidate operator==(long, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(long, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(long, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(long, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(long long, float)
prog.cc:30:8: note: built-in candidate operator==(long long, double)
prog.cc:30:8: note: built-in candidate operator==(long long, long double)
prog.cc:30:8: note: built-in candidate operator==(long long, __float128)
prog.cc:30:8: note: built-in candidate operator==(long long, long)
prog.cc:30:8: note: built-in candidate operator==(long long, long long)
prog.cc:30:8: note: built-in candidate operator==(long long, __int128)
prog.cc:30:8: note: built-in candidate operator==(long long, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(long long, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(long long, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(long long, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(__int128, float)
prog.cc:30:8: note: built-in candidate operator==(__int128, double)
prog.cc:30:8: note: built-in candidate operator==(__int128, long double)
prog.cc:30:8: note: built-in candidate operator==(__int128, __float128)
prog.cc:30:8: note: built-in candidate operator==(__int128, long)
prog.cc:30:8: note: built-in candidate operator==(__int128, long long)
prog.cc:30:8: note: built-in candidate operator==(__int128, __int128)
prog.cc:30:8: note: built-in candidate operator==(__int128, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(__int128, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(__int128, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(__int128, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, float)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, double)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, long double)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, __float128)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, long)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, float)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, double)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, long double)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, __float128)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, float)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, double)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, long double)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, __float128)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, float)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, double)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, long double)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, __float128)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, long)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, unsigned __int128)
1 error generated.

-4

Outro uso comum é para contêineres std fazer comparação de igualdade em valores-chave dentro de objetos personalizados

class Foo
{
    public: int val;
};

class Comparer { public:
bool operator () (Foo& a, Foo&b) const {
return a.val == b.val; 
};

class Blah
{
std::set< Foo, Comparer > _mySet;
};

2
Este é um exemplo de uso, operator ()não operator bool. Eles são totalmente diferentes. operator ()é o operador de chamada, para que a Comparerpossa ser chamado como uma função. Isso operator ()apenas acontece para retornar bool, mas isso não o torna o mesmo que operator bool, o que simplesmente permite uma conversão implícita para bool.
Michael Dorst de
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.