El mecanismo de static_assert();

Iniciado por digimikeh, 15 Junio 2019, 19:20 PM

0 Miembros y 1 Visitante están viendo este tema.

digimikeh

Hola !

He llegado al punto de practicar el static_assert(), entiendo ya como funciona y a que se refiere, seria basicamente una afirmacion a la fuerza y evaluada luego, si es falsa entonoces habra un error, si es verdadera, continuara con el programa.

Lo que entiendo (a diferencia de assert()) es que static_assert evalua en tiempo de compilacion, aqui esto no lo entiendo bien, a que se refiere con tiempo de compilacion ?....  mientras escribes el codigo o cuando haces el build?  Si si, entiendo que esta pregunta es absurda, se supone que tiempo de compilacion es cuando haces build, pero lo pregunto por lo siguiente:

Resulta que estoy en Visual Studio 2017, al escribir:

Código (cpp) [Seleccionar]


int main (){
    static_assert(sizeof(int) == 4, "Su sistema no es de 64bits");
    std::cout << "64 bits.";
   
}


No me va ningun error, es decir, todo bien... pero si le cambio el valor 4 por 5, o por cualquier otro, de inmediato VS me lanza un error, y la descripcion del error es justamente el segundo argumento "Su sistema no es de 64bits", esto quiere decir que static_assert esta evaluando mientras escribo el codigo, no cuando hago build..


Esto definitivamente no puede ser ni tiempo de ejecucion, ni tiempo de compilacion, como le podriamos llamar??..


Editado:
Parece que es el compilador de Microsoft el que hace esta verificacion en el tiempo de edicion, GCC parece no tenerla, no sale el error hasta que le doy build...  entonces SI que es en tiempo de compilacion, pero el compilador de MS te ahorra un poco mas de tiempo mostrandote mientras escribes...
Dungeons & dragons;
dragons.Attack();

@XSStringManolo

Estas haciendo deducciones inventándote cosas. Eso de tiempo de edicion, evaluación mientras escribes código, tiempo de build...
Solo tienes comprobación en tiempo de ejecución. Y comprobación en tiempon de compilación.

Cuando una condición se comprueba en tiempo de compilación quiere decir que mirará el valor que le has puesto. Imagínate este hipotético código:
int bytes = 4;
cout << "Introduce los bytes a comprobar";
cin >> bytes;
static_assert(sizeof(int) == bytes, "Su sistema no es de 64bits");

Al ejecutarse ese código en tiempo de compilación, quiere decir que static_asert comprobará 4 en la condición. Da igual que el usuario cambie el valor de la variable durante la ejecución del programa porque la sentencia ya se comprobó cuando se compiló el código. Eso es "En tiempo de compilación".

Si se comprobase en tiempo de ejecucción, la expresión se evaluaría después de que el usuario pusiese el valor de la variable.

Es así de sencillo. No tiene más complicación.


static_asert se suele usar para no compilar ciertos trozos del programa si ocurre un error.
Por ejemplo yo hago un código e incluyo unas librerías del 2019 de 1gb de tamaño y uso todas las nuevas funciones.
Tu descargas mi código y lo compilas con tus librerías sin actualizar del 2018.
El compilador va a tardar un buen rato en buscar en la librería las funciones para 10 o 20 minutos después darse cuenta de que no existen esas fuciones en la librería. Asique perderías 20 minutos para nada y no sabrías cual es el problema.

Si yo fuí previsor, podría utilizar un static_asert para comprobar la versión de la librería y ahorrarte 29 minutos de tiempo para nada. Ejemplo:
#include "libreria.h"
static_assert(libreria::Version < 2019,  "No estás usando la libreria2019. El programa no compilara. Actualiza en www.libreria.inv/last-version para utilizar el programa);

También puedes usarlo para que te avise al compilar si has hecho algo mal.
Para forzar números aleatorios y todo lo que se te ocurra.

Podría forzar a compilar con un número aleatorio, y como una vez compilado el programa no se volverá a usar un número aleatorio, no dará problemas ese ejecutable. Y podras hacer por ejemplo varios ejecutables con números de serie aleatorios.

int miVariable= estaFuncionRetornaUnIntAleatorioEntre0y100();

static_assert(miVariable>50, "El numero no es mayor que 50, intenta compilar otra vez");

digimikeh

Gracias por la respuesta...
Entiendo todo lo que has puesto, pero no me había enfocado a eso amigo, sino al comportamiento de MSVS 2017, que me corregía al vuelo el problema que había cuando static_assert() estaba detectando...  esto claramente no es tiempo de compilación, por eso puse "Edito" mas abajo, porque me di cuenta que es una característica de MS y no de GCC (por ejemplo)..

Saludos.
Dungeons & dragons;
dragons.Attack();

Loretz

Citar... tiempo de compilacion... mientras escribes el código o haces el build? ...

static_assert como dices, es una comprobación "en tiempo de compilación". Si el compilador detecta una contradicción al evaluar el static_assert suspenderá la compilación (y emitirá el mensaje de error optativo).

Pero... ¿por qué el Visual Studio (y otros IDEs) muestran una marca de error antes de compilar?

Para el caso del editor de código del Visual Studio la herramienta se llama IntelliSense https://docs.microsoft.com/en-us/visualstudio/ide/using-intellisense?view=vs-2019, que entre otras cosas, es la que señala errores con una linea roja y sinuosa (error squiggle), como cuando escribes en un editor de texto con faltas de hortografía.

Este tipo de herramientas (error squiggle, code-completion, symbol searching, go to definition, ...) son muy difíciles de implementar en C++, y durante años han sido una pesadilla para muchos fabricantes de IDEs (y lo son aún), así que no hay que asustarse si alguna vez falla. Imagina un proyecto que demora en compilar 20 minutos, pero el error-squiggle se muestra instantáneamente con cada tecla pulsada.


@XSStringManolo

No tenía ni idea de que existian esas herramientas. Muy interesantes y muy buena info.

digimikeh

entiendo, entonces es del IDE, no del compilador...
podria salvar varios minutos de compilacion...

llego un momento en que me pregunte : para que rayos tengo que darle un segundo argumento con el error si ya de antemano me lo esta señalando...

gracias por las respuestas.
Dungeons & dragons;
dragons.Attack();