Herramientas de usuario

Herramientas del sitio


cpp-avanzado:macros

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anterior Revisión previa
Próxima revisión
Revisión previa
cpp-avanzado:macros [2017/12/06 01:25]
santo
cpp-avanzado:macros [2023/11/29 15:12] (actual)
santo [El porqué de la macro forn]
Línea 29: Línea 29:
 #define dforall(i,​c) for(auto i = (c).rbegin();​ i != (c).rend(); i++) #define dforall(i,​c) for(auto i = (c).rbegin();​ i != (c).rend(); i++)
 </​code>​ </​code>​
 +
 +La siguiente sirve para evitar montones de errores peligrosos y muy difíciles de detectar producto de comparar enteros con y sin signo, ya que ''​.size()''​ retorna un entero sin signo, por lo que al hacerle cuentas resultados como ''​-1''​ automáticamente pasan a $2^{bits}-1$. El ejemplo más común sería escribir algo como ''​if (v.size()-1 >= 0)'',​ que da siempre ''​true'',​ a diferencia de ''​if (SIZE(v)-1 >= 0)''​ que se comporta como uno espera. Pasar inmediatamente a entero con signo evita problemas.
 +<code cpp>
 +#define SIZE(c) int((c).size())
 +</​code>​
 +
 +
  
 La siguiente es muy útil para utilizar con funciones de STL, donde se suele pedir un rango mediante dos iteradores, para pasar directamente una colección completa. La siguiente es muy útil para utilizar con funciones de STL, donde se suele pedir un rango mediante dos iteradores, para pasar directamente una colección completa.
 <code cpp> <code cpp>
-#​define ​all(c) (c).begin(),(c).end()+#​define ​ALL(c) begin(c), end(c)
 </​code>​ </​code>​
-El uso más común de esta macro, es para llamar a la función ''​sort'',​ con ''​sort(all(v))''​ por ejemplo, siendo ''​v''​ un [[:​curso-cpp:​contenedor-vector|vector]]. Sin embargo es útil con muchísimas funciones de la [[cpp-avanzado:​stl:​|STL]],​ como podría ser por ejemplo una instrucción ''​find(all(v), 27)''​.+El uso más común de esta macro, es para llamar a la función ''​sort'',​ con ''​sort(ALL(v))''​ por ejemplo, siendo ''​v''​ un [[:​curso-cpp:​contenedor-vector|vector]]. Sin embargo es útil con muchísimas funciones de la [[cpp-avanzado:​stl:​|STL]],​ como podría ser por ejemplo una instrucción ''​find(ALL(v), 27)''​.
  
 La siguiente sirve para consultar si un elemento está en un [[:​cpp-avanzado:​set|set]] (o [[:​cpp-avanzado:​map|map]]:​ en un map, se consulta si el elemento dado es una **clave** del diccionario). La siguiente sirve para consultar si un elemento está en un [[:​cpp-avanzado:​set|set]] (o [[:​cpp-avanzado:​map|map]]:​ en un map, se consulta si el elemento dado es una **clave** del diccionario).
 <code cpp> <code cpp>
-#​define ​esta(x,c) ((c).find(x) != (c).end())+#​define ​ESTA(x,c) ((c).find(x) != (c).end())
 </​code>​ </​code>​
  
Línea 57: Línea 64:
 typedef long long tint; typedef long long tint;
 typedef long double tdbl; typedef long double tdbl;
-typedef vector<​int>​ vint; 
-typedef pair<​int,​int>​ pint; 
-typedef pair<​tint,​tint>​ ptint; 
 </​code> ​ </​code> ​
  
 +O su equivalente más moderno:
 +
 +<code cpp>
 +using tint = long long;
 +using tdbl = long double;
 +</​code> ​
 +
 +Utilizar ''​tint''​ para indicar el **t**ipo del **int** permite cambiar entre ''​int'',​ ''​unsigned'',​ ''​long long'',​ ''​unsigned long long'',​ ''​__int128'',​ ''​unsigned char'',​ etc fácilmente si se usa siempre ''​tint''​ para los "​valores"​ del programa (mientras que se usa por ejemplo ''​int''​ para los índices de arreglos y colecciones).
 ===== El porqué de la macro forn ===== ===== El porqué de la macro forn =====
  
Línea 72: Línea 84:
 <code cpp> <code cpp>
 forn(i, 10){ forn(i, 10){
-    forn (j, v.size()) {+    forn (j, SIZE(v)) {
  
     }     }
 } }
 </​code>​ </​code>​
- 
-(Comentario:​ en la declaración de la macro hay un ''​int(n)''​ que nos permite que el ''​forn''​ hasta ''​v.size()-1''​ y similares expresiones no tenga un posible bug causado por ser este valor de tipo unsigned, y de paso logra que el compilador no emita un warning por esto.) 
  
 Uno podría entusiarmarse con las macros y hacer la siguiente macro: Uno podría entusiarmarse con las macros y hacer la siguiente macro:
Línea 86: Línea 96:
 </​code>​ </​code>​
  
-**Es una mala idea** definir el ''​forn''​ sin pasarle la variable para indexar, porque eso nos podria ​introducir "bugs ocultos"​ por no ser suficientemente declarativos y esconder cosas en la macro. En este caso, **escondemos una declaración de variables**.+**Es una muy mala idea** definir el ''​forn''​ sin pasarle la variable para indexar, porque eso nos podría ​introducir ​muy fácilmente ​"bugs ocultos"​ por no ser suficientemente declarativos y esconder cosas en la macro. En este caso, **escondemos una declaración de variables ​visibles fuera de la macro**.
  
 Por ejemplo, este código tendría un error oculto usando esa macro Por ejemplo, este código tendría un error oculto usando esa macro
Línea 99: Línea 109:
  
 En general **el objetivo de las macros no es escribir menos caracteres, sino escribir código que evite bugs** simples por repetición o copy-paste. En general **el objetivo de las macros no es escribir menos caracteres, sino escribir código que evite bugs** simples por repetición o copy-paste.
 +
 +Otro ejemplo:
  
 <code cpp> <code cpp>
Línea 108: Línea 120:
 </​code>​ </​code>​
  
-Ese código tiene un bug no evidenteen el segundo for incrementa i en vez de j.+Ese código tiene un bug no evidente ​a simple vista: ​en el segundo for incrementa i en vez de j.
 En cambio, usando la macro forn como la definimos más arriba, sería En cambio, usando la macro forn como la definimos más arriba, sería
  
Línea 119: Línea 131:
 </​code>​ </​code>​
  
-¡Donde ese bug es simplemente **imposible** de escribir!+¡Donde ese bug es simplemente **imposible** de escribir! ​Usar ''​i''​ ambas veces sería el bug más parecido, pero si usamos las [[:​cpp-avanzado:​opciones-gcc|opciones de compilación]] recomendadas tendremos una advertencia por shadow al hacerlo, e incluso sin el warning es un bug mucho más fácil de detectar y corregir.
cpp-avanzado/macros.1512523545.txt.gz · Última modificación: 2017/12/06 01:25 por santo