En c ++ 03 y versiones anteriores, para deshabilitar la advertencia del compilador sobre parámetros no utilizados, generalmente uso dicho código:
#define UNUSED(expr) do { (void)(expr); } while (0)
Por ejemplo
int main(int argc, char *argv[])
{
UNUSED(argc);
UNUSED(argv);
return 0;
}
Pero las macros no son las mejores prácticas para c ++, entonces. ¿Aparece alguna solución mejor con el estándar c ++ 11? Quiero decir, ¿puedo deshacerme de las macros?
¡Gracias por todo!
c++
c++11
unused-variables
inkooboo
fuente
fuente
(void)argc;
es más corto y claro queUNUSED(argc);
unused(argc, argv)
contemplate<class... T> void unused(T&&...){}
. Claro, conciso y sin macros.void foo(int /*unused_arg*/, int used_arg)
Respuestas:
He usado una función con un cuerpo vacío para ese propósito:
template <typename T> void ignore(T &&) { } void f(int a, int b) { ignore(a); ignore(b); return; }
Espero que cualquier compilador serio optimice la llamada a la función y me silencie las advertencias.
fuente
T
es un parámetro de plantilla,T&&
es una referencia universal que se une a cualquier cosa.Puede simplemente omitir los nombres de los parámetros:
int main(int, char *[]) { return 0; }
Y en el caso de main, incluso puede omitir los parámetros por completo:
int main() { // no return implies return 0; }
Consulte "§ 3.6 Inicio y terminación" en el estándar C ++ 11.
fuente
main
, puede omitir los parámetros por completo. Y lareturn
declaración, para el caso.main
'sreturn 0
en un caso de prueba, pero casi siempre escribo la auto-documentaciónreturn EXIT_SUCCESS
en código de producción. ¡Esa es una buena práctica!Está
<tuple>
en C ++ 11 , que incluye elstd::ignore
objeto listo para usar , que nos permite escribir (muy probablemente sin imponer gastos generales de ejecución):void f(int x) { std::ignore = x; }
fuente
Para "deshabilitar" esta advertencia, lo mejor es evitar escribir el argumento, simplemente escriba el tipo.
void function( int, int ) { }
o si lo prefieres coméntalo:
void function( int /*a*/, int /*b*/ ) { }
Puede mezclar argumentos con nombre y sin nombre:
void function( int a, int /*b*/ ) { }
Con C ++ 17 tiene el especificador de atributo [[maybe_unused]], como:
void function( [[maybe_unused]] int a, [[maybe_unused]] int b ) { }
fuente
/* ... */
#if 0
bloques como un caso especial, incluso si no admiten intellisense de preprocesador completo.Nada equivalente, no.
Así que estás atascado con las mismas opciones de siempre. ¿Está contento de omitir los nombres en la lista de parámetros por completo?
int main(int, char**)
En el caso específico de
main
, por supuesto, simplemente podría omitir los parámetros en sí:int main()
También existen los trucos típicos específicos de la implementación, como los de GCC
__attribute__((unused))
.fuente
Las macros pueden no ser ideales, pero hacen un buen trabajo para este propósito en particular. Yo diría que siga usando la macro.
fuente
MAYBE_UNUSED
, por esa razón; Por lo general, no me importa si he dicho "no se preocupe si no uso esto a continuación", pero continúe haciéndolo de todos modos.¿Qué tienes en contra de la forma antigua y estándar?
void f(int a, int b) { (void)a; (void)b; return; }
fuente
No hay nada nuevo disponible.
Lo que me funciona mejor es comentar el nombre del parámetro en la implementación. De esa manera, se deshace de la advertencia, pero aún conserva alguna noción de cuál es el parámetro (ya que el nombre está disponible).
Su macro (y cualquier otro enfoque de conversión a vacío) tiene la desventaja de que realmente puede usar el parámetro después de usar la macro. Esto puede hacer que el código sea más difícil de mantener.
fuente
El encabezado Boost
<boost/core/ignore_unused.hpp>
(Boost> = 1.56) define, para este propósito, la plantilla de funciónboost::ignore_unused()
.int fun(int foo, int bar) { boost::ignore_unused(bar); #ifdef ENABLE_DEBUG_OUTPUT if (foo < bar) std::cerr << "warning! foo < bar"; #endif return foo + 2; }
PS C ++ 17 tiene el
[[maybe_unused]]
atributo de suprimir advertencias sobre entidades no utilizadas.fuente
[[maybe_unused]]
es de forma explícita, actualmente la mejor.Realmente me gusta usar macros para esto, porque le permite un mejor control cuando tiene diferentes compilaciones de depuración (por ejemplo, si desea compilar con afirmaciones habilitadas):
#if defined(ENABLE_ASSERTS) #define MY_ASSERT(x) assert(x) #else #define MY_ASSERT(x) #end #define MY_UNUSED(x) #if defined(ENABLE_ASSERTS) #define MY_USED_FOR_ASSERTS(x) x #else #define MY_USED_FOR_ASSERTS(x) MY_UNUSED(x) #end
y luego úsalo como:
int myFunc(int myInt, float MY_USED_FOR_ASSERTS(myFloat), char MY_UNUSED(myChar)) { MY_ASSERT(myChar < 12.0f); return myInt; }
fuente
Tengo mi propia implementación para segmentos de código de tiempo crítico. He estado investigando por un tiempo un código de tiempo crítico para ralentizar y he descubierto que esta implementación consume alrededor del 2% del código de tiempo crítico que he optimizado:
#define UTILITY_UNUSED(exp) (void)(exp) #define UTILITY_UNUSED2(e0, e1) UTILITY_UNUSED(e0); UTILITY_UNUSED(e1) #define ASSERT_EQ(v1, v2) { UTILITY_UNUSED2(v1, v2); } (void)0
El código de tiempo crítico ha utilizado las
ASSERT*
definiciones con fines de depuración, pero en el lanzamiento claramente se ha cortado, pero ... Parece que este produce un código un poco más rápido enVisual Studio 2015 Update 3
:#define UTILITY_UNUSED(exp) (void)(false ? (false ? ((void)(exp)) : (void)0) : (void)0) #define UTILITY_UNUSED2(e0, e1) (void)(false ? (false ? ((void)(e0), (void)(e1)) : (void)0) : (void)0)
La razón es doble
false ?
expresión. De alguna manera produce un código un poco más rápido en el lanzamiento con la máxima optimización.No sé por qué esto es más rápido (parece un error en la optimización del compilador), pero al menos es una mejor solución para ese caso de código.
Nota : Lo más importante aquí es que un código de tiempo crítico se ralentiza sin las afirmaciones anteriores o macros no utilizadas en el lanzamiento. En otras palabras, la doble
false ?
expresión ayuda sorprendentemente a optimizar un código.fuente
windows.h define UNREFERENCED_PARAMETER :
#define UNREFERENCED_PARAMETER(P) {(P) = (P);}
Entonces podrías hacerlo así:
#include <windows.h> #include <stdio.h> int main(int argc, char **argv) { UNREFERENCED_PARAMETER(argc); puts(argv[1]); return 0; }
O fuera de Windows:
#include <stdio.h> #define UNREFERENCED_PARAMETER(P) {(P) = (P);} int main(int argc, char **argv) { UNREFERENCED_PARAMETER(argc); puts(argv[1]); return 0; }
fuente
operator=
puede tener efectos secundarios.