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/05 22:27]
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 68: Línea 80:
 </​code>​ </​code>​
  
-nos permite, además de parametrizar la cantidad de iteraciones,​ parametrizar la variable que indexa.+nos permite, además de parametrizar la cantidad de iteraciones,​ parametrizar ​**la variable** que indexa.
 Entonces uno puede escribir ​ Entonces uno puede escribir ​
 <code cpp> <code cpp>
 forn(i, 10){ forn(i, 10){
-    forn (j, v.size()) {+    forn (j, SIZE(v)) {
  
     }     }
 } }
 </​code>​ </​code>​
- 
-Notar que en la declaración de la macro hay un int(n) que nos permite que el forn hasta v.size() no tenga un posible bug por ser este valor de tipo unsigned, y que el compilador no tire un warning. ​ 
  
 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>​
  
-Yo no introduciría ​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 indexarporque 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 98: Línea 108:
 Un lector cualquiera asumiría que este código escribe 10 veces el número 24, pero se encontraría con que imprime los números del 1 al 10. Un lector cualquiera asumiría que este código escribe 10 veces el número 24, pero se encontraría con que imprime los números del 1 al 10.
  
-En general **el objetivo de las macros no es escribir menos caracteres, ​si no 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.1512512861.txt.gz · Última modificación: 2017/12/05 22:27 por santo