c++ - Cómo moverse por GCC ''*((void*) & b+4)'' se puede utilizar sin inicializar en esta función de advertencia mientras se usa boost:: optional
g++ boost-optional (4)
Hay dos niveles de análisis no inicializado en gcc:
-
-Wuninitialized
: variables de indicadores que sin duda se utilizan sin inicializar -
-Wmaybe-uninitialized
: variables de indicadores que se utilizan potencialmente sin inicializar
En gcc (*), -Wall
enciende ambos niveles a pesar de que este último tiene advertencias espurias porque el análisis es imperfecto. Las advertencias espurias son una plaga, por lo que la forma más sencilla de evitarlas es pasar -Wno-maybe-uninitialized
-Wall
(después de -Wall
).
Si todavía quiere las advertencias, pero no las tiene causa de error de compilación (a través de -Werror
) puede enumerarlas en blanco usando -Wno-error=maybe-uninitialized
.
(*) Clang no se activa -Wmaybe-uninitialized
por defecto precisamente porque es muy impreciso y tiene un buen número de falsos positivos; Ojalá gcc siguiera esta directriz también.
Tengo un código similar al siguiente:
#include <boost/optional.hpp>
::boost::optional<int> getitem();
int go(int nr)
{
boost::optional<int> a = getitem();
boost::optional<int> b;
if (nr > 0)
b = nr;
if (a != b)
return 1;
return 0;
}
Al compilar con GCC 4.7.2 con Boost 1.53, use el siguiente comando:
g ++ -c -O2 -Wall -DNDEBUG
Se emite la siguiente advertencia:
13: 3: advertencia: '' ((void ) & b +4)'' puede usarse sin inicializar en esta función [-Wmaybe-uninitized]
Aparentemente, el problema de raíz está en GCC. Ver GCC Bugzilla ¿Alguien sabe una solución?
He encontrado que cambiar la construcción de b en el siguiente código (efectivamente igual):
auto b = boost::make_optional(false,0);
elimina la advertencia. Sin embargo, el siguiente código (que también es efectivamente igual):
boost::optional<int> b(false,0);
no elimina la advertencia. Todavía es un poco insatisfactorio ...
Tuve el mismo problema con este fragmento de código:
void MyClass::func( bool repaint, bool cond )
{
boost::optional<int> old = m_sizeLimit; // m_sizeLimit is a boost::optional<int> class attribute
if ( cond )
m_sizeLimit = 60;
else
m_sizeLimit.reset();
if ( repaint )
{
if ( old != m_sizeLimit ) // warning here
doSomething();
}
}
No pude deshacerme de la advertencia con la respuesta de Paul Omta, intenté escribir:
boost::optional<int> old;
if ( m_sizeLimit )
old = boost::make_optional<int>(true, m_sizeLimit.value());
else
old = boost::make_optional<int>(false, 0);
... sin éxito.
No quería desactivar por completo la advertencia de mi código, así que encontré una solución alternativa que recomendaría: desactivar la advertencia localmente:
#ifdef SDE_MOBILE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
if ( old != m_sizeLimit ) // warning here
doSomething();
#ifdef SDE_MOBILE
#pragma GCC diagnostic pop
#endif
Tenía un tipo que no se construyó fácilmente, así que no quería ir a la ruta boost :: make_optional. Asignar una variable automática usando el retorno de una función resolvió este problema para mí. Entonces puedes hacer:
boost::optional<Foo> Default()
{
return boost::none;
}
auto var(Default());
Esto también funcionará como una línea lambda, por lo que puedes hacer:
auto var([]()->boost::optional<Foo> { return boost::none; }());