funciones - Advertencias o errores para la conversión implícita de primitivas en C++
funciones en c++ (6)
En el lenguaje de programación C ++, tercera edición , apéndice C.6, llamado "Conversión de tipo implícita", Bjarne Stroustrup clasifica las conversiones como promociones y conversiones : los primeros "conservan los valores" (ese es su caso 2), los segundos no. (caso 1).
Acerca de las conversiones , dice que "los tipos fundamentales se pueden convertir unos en otros de una manera desconcertante. En mi opinión, se permiten demasiadas conversiones". y "Un compilador puede advertir sobre muchas conversiones cuestionables. Afortunadamente, muchos compiladores sí lo hacen".
Las promociones en el otro lado son seguras, y parece que un compilador no debe dar una advertencia por ellas.
Las advertencias del compilador generalmente no son obligatorias. Por lo general, en los borradores de C ++ y en los documentos ANSI finales , se informa que "los implementadores deben emitir una advertencia" donde se sugiere: puede verificarlo usted mismo para obtener más información si es necesario.
EDITADO: añadido C ++ 11 nota:
En el lenguaje de programación The C ++, 4ª edición , el apéndice de la 3ª edición se informó y se extendió a la sección 10.5, "Conversión de tipo implícita" nuevamente.
Como las consideraciones anteriores son las mismas, C ++ 11 define con mayor precisión las "conversiones de reducción" y agrega la notación inicializadora {} (6.3.5), con la cual los truncamientos conducen a un error de compilación.
He hecho un poco de refactorización de algunos códigos C ++ y descubrí numerosos errores que surgen de conversiones implícitas de las que no tengo conocimiento.
Ejemplo
struct A *a();
bool b() {
return a();
}
void c() {
int64_t const d(b());
}
Cuestiones
- En
b
, el tipo de retorno dea
se convierte silenciosamente abool
. - En
c
, el valor devuelto desdeb
se promueve silenciosamente aint64_t
.
Pregunta
¿Cómo puedo recibir advertencias o errores para la conversión implícita entre tipos primitivos ?
Nota
- El uso de
-Wconversion
parece recoger solo varias conversiones arbitrarias no relacionadas con el ejemplo anterior. -
BOOST_STRONG_TYPEDEF
no es una opción (mis tipos deben ser POD, ya que se usan en estructuras de disco). - C también es de interés, sin embargo, este problema se refiere a una base de código C ++.
Escribe un complemento personalizado para diagnosticar tus problemas. Hacemos mucho de esto en el código de LibreOffice. Visite nuestra fuente si desea inspiración en http://cgit.freedesktop.org/libreoffice/core/tree/compilerplugins/clang
Microsoft Visual C ++ daría una advertencia sobre la conversión de reducción de A*
a bool
.
Ver el Compilador de Advertencia C4800
Por otro lado, la promoción no es una conversión "peligrosa", porque es imposible perder datos.
EDITAR: Demostración
C:/Users/Ben>copy con test.cpp
bool f( void ) { return new int(); }
^Z
1 file(s) copied.
C:/Users/Ben>cl /c /W4 test.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
test.cpp
test.cpp(1) : warning C4800: ''int *'' : forcing value to bool ''true'' or ''false'' (
performance warning)
Puede usar una de las herramientas de análisis estático disponibles, programas como clint o equivalentes de C ++, o una de las herramientas disponibles comercialmente. Muchas de estas herramientas pueden detectar conversiones implícitas problemáticas.
Según tengo entendido, no puede controlar la conversión implícita entre tipos primitivos: es obligatorio por el estándar y cualquier compilador compatible solo lo ejecutará en silencio.
¿Estás seguro de que un enfoque como BOOST_STRONG_TYPEDEF no funcionará en tu problema? Una clase sin funciones de miembro virtual y solo un miembro de datos primitivos es básicamente nada más que un tipo de datos POD. Simplemente puede seguir el mismo enfoque y solo permitir la conversión al tipo primitivo básico; ejemplo:
#include <iostream>
#include <stdexcept>
struct controlled_int {
// allow creation from int
controlled_int(int x) : value_(x) { };
controlled_int& operator=(int x) { value_ = x; return *this; };
// disallow assignment from bool; you might want to use BOOST_STATIC_ASSERT instead
controlled_int& operator=(bool b) { throw std::logic_error("Invalid assignment of bool to controlled_int"); return *this; };
// creation from bool shouldn''t happen silently
explicit controlled_int(bool b) : value_(b) { };
// conversion to int is allowed
operator int() { return value_; };
// conversion to bool errors out; you might want to use BOOST_STATIC_ASSERT instead
operator bool() { throw std::logic_error("Invalid conversion of controlled_int to bool"); };
private:
int value_;
};
int main()
{
controlled_int a(42);
// This errors out:
// bool b = a;
// This gives an error as well:
//a = true;
std::cout << "Size of controlled_int: " << sizeof(a) << std::endl;
std::cout << "Size of int: " << sizeof(int) << std::endl;
return 0;
}
Si está utilizando gcc, ha intentado -Wall -Wextra, básicamente, consulte esta página
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
Si no es GCC por favor publique los detalles del compilador.