Tengo el siguiente código

  class C
    {
    public:
        C(bool v_):v(v_){};
        explicit operator bool() const {return v;}
        bool v = false;    
    };

 int main(){
  C a{true};
  C b{false};
  // C d = true; // doesn't compile, since requires explicit conversion
  C d = static_cast<bool>(true); // fine

  if(a || b) std::cout << "conversion happened!" << std::endl; // why it doesn't require explicit conversion here?

 }

Produce "¡conversión sucedió!". Mi pregunta es ¿por qué || se considera una conversión explícita?

Editar

  // C d = true; // actually this line compiles because of the constructor
c++
4
Allanqunzi 5 mar. 2017 a las 23:55

2 respuestas

La mejor respuesta

De [expr.log.or]:

Los operandos se convierten contextualmente a bool

La conversión contextual a bool puede usar conversiones explícitas. Ese es el punto del concepto de "contextualidad": la conversión explícita se permite precisamente cuando tiene sentido, y no de otra manera, por lo que no forma accidentalmente valores integrales o punteros arbitrarios a partir de la conversión bool, sino cuando realmente solicita un bool, lo entiendes.

Ver [conv] / 4 para más detalles:

Ciertas construcciones de lenguaje requieren que una expresión se convierta en un valor booleano. Una expresión e que aparece en dicho contexto se dice que está convertido contextualmente a bool y está bien formado si y solo si la declaración bool t(e); está bien formada, para algunas variables temporales inventadas t

7
Kerrek SB 5 mar. 2017 a las 20:59

Desde el estándar C ++ (4 conversiones estándar)

4 Ciertas construcciones del lenguaje requieren que una expresión se convierta a un valor booleano. Una expresión que aparece en dicho contexto es se dice que está convertido contextualmente a bool y está bien formado si y solo si la declaración bool t (e); está bien formado, para algunos variable temporal inventada t (8.5).

Y (5.15 Operadora lógica OR)

1 El || grupos de operadores de izquierda a derecha. Los operandos son ambos convertido contextualmente a bool (Cláusula 4). Devuelve verdadero si alguno de sus operandos es verdadero, y falso de lo contrario. A diferencia de |, || garantiza la evaluación de izquierda a derecha; Además, el segundo operando es no evaluado si el primer operando se evalúa como verdadero.

Y por fin (12.3.2 Funciones de conversión)

2 Una función de conversión puede ser explícita (7.1.2), en cuyo caso es solo se considera como una conversión definida por el usuario para inicialización directa (8.5). De lo contrario, las conversiones definidas por el usuario no están restringidas al uso en asignaciones e inicializaciones.

En relación con su ejemplo, la declaración inventada de la variable t

C c( true );

bool t( c ); 

Está bien formado porque se usa la inicialización directa.

1
Vlad from Moscow 5 mar. 2017 a las 21:16