

La biblioteca de afirmación de C ++ con más ingeniería
Filosofía de la biblioteca: proporcione la mayor cantidad posible de información de diagnóstico útil.
Algunas de las cosas increíbles que hace la biblioteca:
void zoog ( const std::map<std::string, int >& map) {
DEBUG_ASSERT (map. contains ( " foo " ), " expected key not found " , map);
}
ASSERT (vec.size() > min_items(), "vector doesn't have enough items", vec);
std::optional< float > get_param ();
float f = * ASSERT_VAL (get_param());
Tipos de afirmaciones:
Afirmaciones condicionales:
DEBUG_ASSERT : revisado en depuración pero pero no hace nada en el lanzamiento (análoga a la assert de la biblioteca estándar)ASSERT : Verificado tanto en la depuración como en el lanzamientoASSUME : Verificado en la depuración y sirve como una pista de optimización en el lanzamientoAfirmaciones incondicionales:
PANIC : desencadena tanto en depuración como en lanzamientoUNREACHABLE : desencadenantes en depuración, marcados como inalcanzables en el lanzamiento ¿Prefiere assert lowecase?
Puede habilitar los alias debug_assert en minúsculas y assert con -DLIBASSERT_LOWERCASE .
Resumen de características:
ASSERT_EQ , etc.DEBUG_ASSERT_VAL y ASSERT_VAL variantes que devuelven un valor para que puedan integrarse sin problemas en el código, por ejemplo FILE* f = ASSERT_VAL(fopen(path, "r") != nullptr) include (FetchContent)
FetchContent_Declare(
libassert
GIT_REPOSITORY https://github.com/jeremy-rifkin/libassert.git
GIT_TAG v2.1.2 # <HASH or TAG>
)
FetchContent_MakeAvailable(libassert)
target_link_libraries (your_target libassert::assert)
# On windows copy libassert.dll to the same directory as the executable for your_target
if ( WIN32 )
add_custom_command (
TARGET your_target POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:libassert::assert>
$<TARGET_FILE_DIR:your_target>
)
endif () Asegúrese de configurar con -DCMAKE_BUILD_TYPE=Debug o -DDCMAKE_BUILD_TYPE=RelWithDebInfo para símbolos e información de línea.
En MacOS se recomienda generar un archivo .dsym, consulte la logística de la plataforma a continuación.
Para otras formas de usar la biblioteca, como a través de los administradores de paquetes o una instalación de todo el sistema, consulte el uso a continuación.
Fundamentalmente, el papel de las afirmaciones es verificar los supuestos hechos en el software e identificar violaciones cercanas a sus fuentes. Las herramientas de afirmación deben priorizar proporcionar tanta información y contexto al desarrollador como sea posible para permitir el triaje rápido. Desafortunadamente, las herramientas existentes en el idioma y la biblioteca proporcionan información de triaje muy limitada.
Por ejemplo con las afirmaciones de stdlib una afirmación como assert(n <= 12); No proporciona información sobre el fracaso sobre por qué falló o qué conduce a su falla. Proporcionar un rastro de pila y el valor de n Greatley mejora el triaje y la depuración. Idealmente, una falla de afirmación debe proporcionar suficiente información de diagnóstico que el Programmmer no tenga que volver a ejecutar en un depurador para identificar el problema.
La versión 1 de esta biblioteca fue una exploración que analizó cuánta información y funcionalidad útiles podrían empaquetarse en afirmaciones al tiempo que proporcionan una interfaz rápida y fácil para el desarrollador.
La versión 2 de esta biblioteca requiere lecciones aprendidas de la versión 1 para crear una herramienta que personalmente he encontrado indispensable en el desarrollo.
La característica más importante que admite esta biblioteca es la descomposición de expresión automática. No hay necesidad de ASSERT_LT u otra vez, assert(vec.size() > 10); se entiende automáticamente, como se muestra anteriormente.
Se muestran los valores involucrados en las expresiones de afirmación. Se evitan los diagnósticos redundantes como 2 => 2 .
DEBUG_ASSERT (map.count( 1 ) == 2);
Solo la expresión de afirmación completa se puede extraer de una llamada macro. Mostrar qué partes de la expresión corresponden a qué valores requiere un análisis de expresión básica. La gramática C ++ es ambigua, pero la mayoría de las expresiones se pueden desambiguar.
Todas las afirmaciones en esta biblioteca admiten mensajes de diagnóstico opcionales, así como otros mensajes de diagnóstico arbitrarios.
FILE* f = ASSERT_VAL(fopen(path, " r " ) != nullptr , " Internal error with foobars " , errno, path); Se proporciona un manejo especial para errno , y Strerror se llama automáticamente.
Nota: El diagnóstico adicional solo se evalúa en la ruta de falla de una afirmación.

Se ha realizado mucho trabajo para generar trazas de pila bonitas y formatearlos lo más bien posible. CPPTRACE se usa como una solución portátil y autónoma para las pilas pre-C ++ 23. Las configuraciones opcionales se pueden encontrar en la documentación de la biblioteca.
Una característica que vale la pena señalar es que, en lugar de imprimir siempre rutas completas, solo se imprimen el número mínimo de directorios necesarios para diferenciar las rutas.

Otra característica que vale la pena señalar es que las trazas de pila doblarán rastros con una recursión profunda:

El controlador de afirmación aplica la sintaxis destacando donde sea apropiado, como se ve en todas las capturas de pantalla anteriores. Esto es para ayudar a mejorar la legibilidad.
Libassert admite manejadores de falla de afirmación personalizada:
void handler (assert_type type, const assertion_info& assertion) {
throw std::runtime_error ( " Assertion failed: n " + assertion. to_string ());
}
int main () {
libassert::set_failure_handler (handler);
} Se ofrece mucho cuidado al producir las estrictas de depuración de valores de la manera más efectiva posible: cadenas, caracteres, números, deben imprimirse como era de esperar. Además, los contenedores, las tuplas, las std :: opcionales, los punteros inteligentes, etc. están triturados para mostrar la mayor cantidad de información posible. Si un operator<<(std::ostream& o, const S& s) , se llamará a esa sobrecarga. De lo contrario, se imprimirá un mensaje predeterminado. Además, se proporciona un punto Stringification Customiztaion:
template <> struct libassert ::stringifier<MyObject> {
std::string stringify ( const MyObject& type) {
return ...;
}
};

Los valores de afirmación se imprimen en hexadecimal o binario, así como decimal si hex/binario se usan a ambos lados de una expresión de afirmación:
ASSERT (get_mask() == 0b00001101);
Debido a que las expresiones ya se descomponen automáticamente, puede optar por haber firmado comparaciones no firmadas realizadas automáticamente con Sign Safety con -DLIBASSERT_SAFE_COMPARISONS :
ASSERT ( 18446744073709551606ULL == - 10 );
Libassert proporciona dos encabezados <libassert/assert-catch2.hpp> y <libassert/assert-gtest.hpp> para usar con Catch2 y Googletest.
Salida de ejemplo de GTEST:

Más información a continuación.
Libassert proporciona tres tipos de afirmaciones, cada uno que varía ligeramente dependiendo de cuándo debe verificarse y cómo debe interpretarse:
| Nombre | Efecto |
|---|---|
DEBUG_ASSERT | Verificado en la depuración, sin codegen en la versión |
ASSERT | Verificado en depuración y construcción de lanzamiento |
ASSUME | Verificado en la depuración, if(!(expr)) { __builtin_unreachable(); } en el lanzamiento |
Afirmaciones incondicionales
| Nombre | Efecto |
|---|---|
PANIC | Desencadenantes tanto en depuración como en lanzamiento |
UNREACHABLE | Desencadenado en depuración, marcado como inalcanzable en el lanzamiento. |
Un beneficio para PANIC e UNREACHABLE , ASSERT(false, ...) es que el compilador obtiene información [[noreturn]] .
ASSUME marca la ruta de falla como inalcanzable en la versión, potencialmente proporcionando información útil al optimizador. Este no es el comportamiento predeterminado para todas las afirmaciones porque la consecuencia inmediata de esto es que la falla de afirmación en -DNDEBUG puede conducir a UB y es mejor hacer esto muy explícito.
Variantes de afirmación que se pueden usar en línea en una expresión, como FILE* file = ASSERT_VAL(fopen(path, "r"), "Failed to open file"); , también están disponibles:
| Nombre | Efecto |
|---|---|
DEBUG_ASSERT_VAL | Verificado en la depuración, debe evaluarse tanto en la depuración como en la liberación |
ASSERT_VAl | Verificado en depuración y construcción de lanzamiento |
ASSUME_VAL | Verificado en la depuración, if(!(expr)) { __builtin_unreachable(); } en el lanzamiento |
Nota: Incluso en la versión construye la expresión de DEBUG_ASSERT_VAL , aún debe ser evaluada, a diferencia de DEBUG_ASSERT . Por supuesto, si el resultado no se usa y no produce efectos secundarios, se optimizará.
Rendimiento: en lo que respecta al rendimiento del tiempo de ejecución, el impacto en las llamadas es muy mínimo bajo -Og o superior. El camino rápido en el código (es decir, donde la afirmación no falla), será rápido. Se requiere mucho trabajo para procesar fallas de afirmación una vez que suceden. Sin embargo, dado que las fallas deberían ser raras, esto no debería importar.
Velocidades de compilación: hay un costo de tiempo de compilación asociado con todas las instancias de plantilla requeridas para la magia de esta biblioteca.
Otro:
Nota
Debido a la descomposición de la expresión, ASSERT(1 = 2); compilación.
Todas las funciones de afirmación son macros. Aquí hay algunas pseudo-declaraciones para interactuar con ellos:
void DEBUG_ASSERT (expression, [optional message], [optional extra diagnostics, ...]);
void ASSERT (expression, [optional message], [optional extra diagnostics, ...]);
void ASSUME (expression, [optional message], [optional extra diagnostics, ...]);
decltype ( auto ) DEBUG_ASSERT_VAL(expression, [optional message], [optional extra diagnostics, ...]);
decltype ( auto ) ASSERT_VAL (expression, [optional message], [optional extra diagnostics, ...]);
decltype ( auto ) ASSUME_VAL (expression, [optional message], [optional extra diagnostics, ...]);
void PANIC ([optional message], [optional extra diagnostics, ...]);
void UNREACHABLE ([optional message], [optional extra diagnostics, ...]); -DLIBASSERT_PREFIX_ASSERTIONS se puede usar para prefijar estas macros con LIBASSERT_ . Esto es útil para envolver las afirmaciones de Libassert.
-DLIBASSERT_LOWERCASE se puede utilizar para habilitar los alias debug_assert y assert para DEBUG_ASSERT y ASSERT . Ver: Reemplazo de <cassert>.
expression La expression se descompone automáticamente para que se pueda proporcionar información de diagnóstico. El tipo resultante debe ser convertible para booleano.
La operación entre los lados de la izquierda y la derecha de la operación de nivel superior en el árbol de expresión se evalúa mediante un objeto de función.
Nota: los operadores lógicos booleanos ( && y || ) no se descomponen de forma predeterminada debido a cortocircuitantes.
assertion message Se puede proporcionar un mensaje de afirmación opcional. Si el primer argumento que sigue a la expresión de afirmación, o el primer argumento en Panic/inalcanzable, es cualquier tipo de cadena, se usará como el mensaje (si desea el primer parámetro, que es una cadena, para ser un valor de diagnóstico adicional, simplemente pase primero una cadena vacía, es decir, ASSERT(foo, "", str); .).).
Nota: La expresión del mensaje de afirmación solo se evalúa en la ruta de falla de la afirmación.
extra diagnosticsSe puede proporcionar un número arbitrario de valores de diagnóstico adicionales. Estos se muestran debajo del diagnóstico de expresión si falla una verificación.
Nota: El diagnóstico adicional solo se evalúa en la ruta de falla de la afirmación.
Hay un manejo especial cuando se proporciona errno : el valor de strerror se muestra automáticamente.
Para facilitar la facilidad de integración en el código, se proporcionan variantes _VAL que devuelven un valor de la expresión de afirmación. El valor devuelto se determina de la siguiente manera:
ASSERT_VAL(foo()); o ASSERT_VAL(false); ) En la expresión de afirmación, el valor de la expresión simplemente se devuelve.== , != , < , <= , > , >= , && , || , o cualquier asignación o asignación de compuesto, entonces se devuelve el valor del operando izquierdo .& , | , ^ , << , >> , o cualquier operador binario con precedencia por encima del desplazamiento de bits, entonces se devuelve el valor de toda la expresión. Es decir, ASSERT_VAL(foo() > 2); Devuelve el resultado calculado de foo() y ASSERT_VAL(x & y); Devuelve el resultado calculado de x & y ;
Si el valor de la expresión de afirmación seleccionada para devolver es un LValue, el tipo de llamada de afirmación será una referencia de LValue. Si el valor de la expresión de afirmación es un rValue, el tipo de llamada será un rValue.
namespace libassert {
[[nodiscard]] std::string stacktrace (
int width = 0 ,
const color_scheme& scheme = get_color_scheme(),
std::size_t skip = 0
);
template < typename T> [[nodiscard]] std::string_view type_name () noexcept ;
template < typename T> [[nodiscard]] std::string pretty_type_name () noexcept ;
template < typename T> [[nodiscard]] std::string stringify ( const T& value);
}stacktrace : genera un rastro de pila, formatos al ancho dado (0 para ningún formato de ancho)type_name : devuelve el nombre de tipo de tpretty_type_name : devuelve el nombre de tipo prettificado para tstringify : produce una cicatrización de depuración de un valor namespace libassert {
void enable_virtual_terminal_processing_if_needed ();
inline constexpr int stdin_fileno = 0 ;
inline constexpr int stdout_fileno = 1 ;
inline constexpr int stderr_fileno = 2 ;
bool isatty ( int fd);
[[nodiscard]] int terminal_width ( int fd);
}enable_virtual_terminal_processing_if_needed : habilitar secuencias de escape ANSI para terminales en ventanas, necesarias para la salida de color.isatty : devuelve verdadero si el descriptor de archivo corresponde a un terminalterminal_width : Devuelve el ancho del terminal representado por FD o 0 en error namespace libassert {
// NOTE: string view underlying data should have static storage duration, or otherwise live as
// long as the scheme is in use
struct color_scheme {
std::string_view string, escape, keyword, named_literal, number, punctuation, operator_token,
call_identifier, scope_resolution_identifier, identifier, accent, unknown, reset;
static const color_scheme ansi_basic;
static const color_scheme ansi_rgb;
static const color_scheme blank;
};
void set_color_scheme ( const color_scheme&);
const color_scheme& get_color_scheme ();
} Por defecto, se utiliza color_scheme::ansi_rgb . Para deshabilitar los colores, use color_scheme::blank .
set_color_scheme : establece el esquema de color para el controlador de afirmación predeterminado cuando Stderr es un terminal namespace libassert {
void set_separator (std::string_view separator);
}set_separator : establece el separador entre expresión y valor en la salida de diagnóstico de afirmación. Predeterminado: => . Nota: no a Safe de hilo. namespace libassert {
enum class literal_format_mode {
infer, // infer literal formats based on the assertion condition
no_variations, // don't do any literal format variations, just default
fixed_variations // always use a fixed set of formats (in addition to the default format)
};
void set_literal_format_mode (literal_format_mode);
enum class literal_format : unsigned {
// integers and floats are decimal by default, chars are of course chars, and everything
// else only has one format that makes sense
default_format = 0 ,
integer_hex = 1 ,
integer_octal = 2 ,
integer_binary = 4 ,
integer_character = 8 , // format integers as characters and characters as integers
float_hex = 16 ,
};
[[nodiscard]] constexpr literal_format operator |(literal_format a, literal_format b);
void set_fixed_literal_format (literal_format);
}set_literal_format_mode : establece si la biblioteca debe mostrar variaciones literal o inferirlasset_fixed_literal_format : establecer una configuración de formato literal fija, cambia automáticamente el literal_format_mode; Tenga en cuenta que el formato predeterminado siempre se usará junto con otros namespace libassert {
enum class path_mode {
full, // full path is used
disambiguated, // only enough folders needed to disambiguate are provided
basename, // only the file name is used
};
LIBASSERT_EXPORT void set_path_mode (path_mode mode);
}set_path_mode : establece el modo de acortamiento de ruta para la salida de afirmación. Predeterminado: path_mode::disambiguated . namespace libassert {
enum class assert_type {
debug_assertion,
assertion,
assumption,
panic,
unreachable
};
struct LIBASSERT_EXPORT binary_diagnostics_descriptor {
std::string left_expression;
std::string right_expression;
std::string left_stringification;
std::string right_stringification;
};
struct extra_diagnostic {
std::string_view expression;
std::string stringification;
};
struct LIBASSERT_EXPORT assertion_info {
std::string_view macro_name;
assert_type type;
std::string_view expression_string;
std::string_view file_name;
std:: uint32_t line;
std::string_view function;
std::optional<std::string> message;
std::optional<binary_diagnostics_descriptor> binary_diagnostics;
std::vector<extra_diagnostic> extra_diagnostics;
size_t n_args;
std::string_view action () const ;
const cpptrace::raw_trace& get_raw_trace () const ;
const cpptrace::stacktrace& get_stacktrace () const ;
[[nodiscard]] std::string header ( int width = 0 , const color_scheme& scheme = get_color_scheme()) const ;
[[nodiscard]] std::string tagline ( const color_scheme& scheme = get_color_scheme()) const ;
[[nodiscard]] std::string location () const ;
[[nodiscard]] std::string statement ( const color_scheme& scheme = get_color_scheme()) const ;
[[nodiscard]] std::string print_binary_diagnostics ( int width = 0 , const color_scheme& scheme = get_color_scheme()) const ;
[[nodiscard]] std::string print_extra_diagnostics ( int width = 0 , const color_scheme& scheme = get_color_scheme()) const ;
[[nodiscard]] std::string print_stacktrace ( int width = 0 , const color_scheme& scheme = get_color_scheme()) const ;
[[nodiscard]] std::string to_string ( int width = 0 , const color_scheme& scheme = get_color_scheme()) const ;
};
} Debug Assertion failed at demo.cpp:194: void foo::baz(): Internal error with foobars
debug_assert(open(path, 0) >= 0, ...);
Where:
open(path, 0) => -1
Extra diagnostics:
errno => 2 "No such file or directory"
path => "/home/foobar/baz"
Stack trace:
#1 demo.cpp:194 foo::baz()
#2 demo.cpp:172 void foo::bar<int>(std::pair<int, int>)
#3 demo.cpp:396 main
Debug Assertion failed : assertion_info.action()demo.cpp:194 : assertion_info.file_name y assertion_info.linevoid foo::baz() : assertion_info.pretty_functionInternal error with foobars : assertion_info.messagedebug_assert : assertion_info.macro_nameopen(path, 0) >= 0 : assertion_info.expression_string... : Determinado por assertion_info.n_args que tiene el número total de argumentos pasados a la macro de afirmaciónopen(path, 0) : assertion_info.binary_diagnostics.left_expression-1 : assertion_info.binary_diagnostics.left_stringification0 => 0 no es útil)errno : assertion_info.extra_diagnostics[0].expression2 "No such file or directory" : assertion_info.extra_diagnostics[0].stringificationassertion_info.get_stacktrace() , o assertion_info.get_raw_trace() para obtener el rastreo sin resolverloAyudantes:
assertion_info.header() ::
Debug Assertion failed at demo.cpp:194: void foo::baz(): Internal error with foobars
debug_assert(open(path, 0) >= 0, ...);
Where:
open(path, 0) => -1
Extra diagnostics:
errno => 2 "No such file or directory"
path => "/home/foobar/baz"
assertion_info.tagline() ::
Debug Assertion failed at demo.cpp:194: void foo::baz(): Internal error with foobars
assertion_info.location() ::
Nota
El procesamiento de ruta se realizará de acuerdo con el modo de ruta
demo.cpp:194
assertion_info.statement() ::
debug_assert(open(path, 0) >= 0, ...);
assertion_info.print_binary_diagnostics() ::
Where:
open(path, 0) => -1
assertion_info.print_extra_diagnostics() ::
Extra diagnostics:
errno => 2 "No such file or directory"
path => "/home/foobar/baz"
assertion_info.print_stacktrace() :
Stack trace:
#1 demo.cpp:194 foo::baz()
#2 demo.cpp:172 void foo::bar<int>(std::pair<int, int>)
#3 demo.cpp:396 main
Libassert proporciona un punto de personalización para los tipos definidos por el usuario:
template <> struct libassert ::stringifier<MyObject> {
std::string stringify ( const MyObject& type) {
return ...;
}
};Por defecto, cualquier tipo definido por el usuario similar al contenedor será automáticamente triturable.
Además, LIBASSERT_USE_FMT se puede usar para permitir que Libassert use fmt::formatter s.
Por último, cualquier tipo con un operator<< sobrecarga se puede triunfar.
namespace libassert {
void set_failure_handler ( void (*handler)( const assertion_info&));
}set_failure_handler : establece el controlador de afirmación para el programa.Un manejador de afirmación de ejemplo similar al controlador predeterminado:
void libassert_default_failure_handler ( const assertion_info& info) {
libassert::enable_virtual_terminal_processing_if_needed (); // for terminal colors on windows
std::string message = info. to_string (
libassert::terminal_width (libassert::stderr_fileno),
libassert::isatty (libassert::stderr_fileno)
? libassert::get_color_scheme ()
: libassert::color_scheme::blank
);
std::cerr << message << std::endl;
switch (info. type ) {
case libassert::assert_type::assertion:
case libassert::assert_type::debug_assertion:
case libassert::assert_type::assumption:
case libassert::assert_type::panic:
case libassert::assert_type::unreachable:
( void ) fflush (stderr);
std::abort ();
// Breaking here as debug CRT allows aborts to be ignored, if someone wants to make a
// debug build of this library
break ;
default :
std::cerr << " Critical error: Unknown libassert::assert_type " << std::endl;
std::abort ( 1 );
}
}Por defecto, Libassert aborta de todos los tipos de afirmación. Sin embargo, puede ser deseable lanzar una excepción de algunos o todos los tipos de afirmación en lugar de abortar.
Importante
Los manejadores de falla no deben regresar para assert_type::panic y assert_type::unreachable .
Libassert admite puntos de ruptura programáticos sobre la falla de afirmación para hacer que las afirmaciones sean más amigables para depuradores al romper en la línea de afirmación en lugar de varias capas de profundidad en un Callstack:

Esta funcionalidad se opta actualmente y se puede habilitar definiendo LIBASSERT_BREAK_ON_FAIL . Esto se hace mejor como una bandera del compilador: -DLIBASSERT_BREAK_ON_FAIL o /DLIBASSERT_BREAK_ON_FAIL .
Internamente, la biblioteca verifica el presente de un depurador antes de ejecutar una instrucción para romper el punto del depurador. Por defecto, la verificación solo se realiza una vez en la primera falla de afirmación. En algunos escenarios, puede ser deseable configurar esta verificación para que siempre se realice, por ejemplo, si está utilizando un controlador de afirmación personalizado que arroja una excepción en lugar de abortar y puede recuperarse de una falla de afirmación que permite fallas adicionales más tarde y solo adjunta un depurador a la parcora a través de su programa. Puede usar libassert::set_debugger_check_mode para controlar cómo se realiza esta verificación:
namespace libassert {
enum class debugger_check_mode {
check_once,
check_every_time,
};
void set_debugger_check_mode (debugger_check_mode mode) noexcept ;
}La biblioteca también expone sus utilidades internas para establecer puntos de ruptura y verificar si el programa está siendo depurado:
namespace libassert {
bool is_debugger_present () noexcept ;
}
# define LIBASSERT_BREAKPOINT () <...internals...>
# define LIBASSERT_BREAKPOINT_IF_DEBUGGING () <...internals...>Esta API imita la API de P2514, que ha sido aceptada para C ++ 26.
Sin embargo, se requiere una nota sobre constexpr : para Libassert de CLANG y MSVC puede usar intrínsecs del compilador. El ensamblaje en línea no está permitido en las funciones de constexpr antes de C ++ 20, sin embargo, GCC lo admite con una advertencia después de GCC 10 y la biblioteca puede sorprender esa advertencia para GCC 12.
Define:
LIBASSERT_USE_MAGIC_ENUM : use mágico enum para los valores de enum.LIBASSERT_DECOMPOSE_BINARY_LOGICAL : descompose && y ||LIBASSERT_SAFE_COMPARISONS : habilitar comparaciones seguras firmadas sin fines de expresiones descompuestasLIBASSERT_PREFIX_ASSERTIONS : prefijos todas las macros de afirmación con LIBASSERT_LIBASSERT_USE_FMT : habilita la integración de libfmtLIBASSERT_NO_STRINGIFY_SMART_POINTER_OBJECTS : deshabilita la cadena de contenido de puntero inteligenteCMake:
LIBASSERT_USE_EXTERNAL_CPPTRACE : use un cpptrace externo en lugar de acuñar la biblioteca con fetchcontentLIBASSERT_USE_EXTERNAL_MAGIC_ENUM : use un enum de mágico externam en lugar de acumular la biblioteca con fetchcontentNota
Debido al preprocesador no conformador de MSVC, no hay una manera fácil de proporcionar envoltorios de afirmación. Para usar las integraciones de la biblioteca de prueba /Zc:preprocessor .
Libassert proporciona una integración Catch2 en libassert/assert-catch2.hpp :
# include < libassert/assert-catch2.hpp >
TEST_CASE ( " 1 + 1 is 2 " ) {
ASSERT ( 1 + 1 == 3 );
}
Actualmente, la única macro proporcionada es ASSERT , que realizará un REQUIRE internamente.
Nota: Antes de V3.6.0, los códigos de color ANSI interfieren con el envoltorio de línea de Catch2 para que el color se desactive en versiones anteriores.
Libassert proporciona una integración GTEST en libassert/assert-gtest.hpp :
# include < libassert/assert-gtest.hpp >
TEST (Addition, Arithmetic) {
ASSERT ( 1 + 1 == 3 );
}
Actualmente, Libassert proporciona Macros ASSERT y EXPECT para GTEST.
Esto no es tan bonito como me gustaría, sin embargo, hace el trabajo.
Esta biblioteca se dirige> = C ++ 17 y admite todos los compiladores principales y todas las plataformas principales (Linux, MacOS, Windows y MingW).
Nota: La biblioteca confía en algunas extensiones del compilador y características específicas del compilador para que no sea compatible con -pedantic .
Con cmake fetchContent:
include (FetchContent)
FetchContent_Declare(
libassert
GIT_REPOSITORY https://github.com/jeremy-rifkin/libassert.git
GIT_TAG v2.1.2 # <HASH or TAG>
)
FetchContent_MakeAvailable(libassert)
target_link_libraries (your_target libassert::assert)Nota: En Windows y MacOS se recomienda un trabajo adicional, consulte la logística de la plataforma a continuación.
Asegúrese de configurar con -DCMAKE_BUILD_TYPE=Debug o -DDCMAKE_BUILD_TYPE=RelWithDebInfo para símbolos e información de línea.
git clone https://github.com/jeremy-rifkin/libassert.git
git checkout v2.1.2
mkdir libassert/build
cd libassert/build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j
sudo make installUsando a través de cmake:
find_package (libassert REQUIRED)
target_link_libraries (<your target > libassert::assert) Asegúrese de configurar con -DCMAKE_BUILD_TYPE=Debug o -DDCMAKE_BUILD_TYPE=RelWithDebInfo para símbolos e información de línea.
O compilar con -lassert :
g++ main.cpp -o main -g -Wall -lassert
./mainSi recibe un error en la línea de
error while loading shared libraries: libassert.so: cannot open shared object file: No such file or directory
Es posible que deba ejecutar sudo /sbin/ldconfig para crear enlaces necesarios y actualizar cachés para que el sistema pueda encontrar libcpptrace.so (tuve que hacer esto en Ubuntu). Solo al instalar en todo el sistema. Por lo general, su pesebre de paquetes hace esto por usted al instalar nuevas bibliotecas.
git clone https: // github.com / jeremy - rifkin / libassert.git
git checkout v2. 1.2
mkdir libassert / build
cd libassert / build
cmake . . - DCMAKE_BUILD_TYPE = Release
msbuild libassert.sln
msbuild INSTALL.vcxprojNota: Deberá ejecutar como administrador en un desarrollador PowerShell, o usar VCVarsall. Bat distribuido con Visual Studio para obtener el conjunto de variables de entorno correctas.
Para instalar solo para el usuario local (o cualquier prefijo personalizado):
git clone https://github.com/jeremy-rifkin/libassert.git
git checkout v2.1.2
mkdir libassert/build
cd libassert/build
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX= $HOME /wherever
make -j
sudo make installUsando a través de cmake:
find_package (libassert REQUIRED PATHS $ENV{HOME} /wherever)
target_link_libraries (<your target > libassert::assert)Usando manualmente:
g++ main.cpp -o main -g -Wall -I$HOME/wherever/include -L$HOME/wherever/lib -lassert
Para usar la biblioteca sin CMake, primero siga las instrucciones de instalación en la instalación de todo el sistema, la instalación local del usuario o los administradores de paquetes.
Use los siguientes argumentos para compilar con Libassert:
| Compilador | Plataforma | Dependencias |
|---|---|---|
| GCC, Clang, Intel, etc. | Linux/macOS/Unix | -libassert -I[path] [cpptrace args] |
| mingw | Windows | -libassert -I[path] [cpptrace args] |
| MSVC | Windows | assert.lib /I[path] [cpptrace args] |
| sonido metálico | Windows | -libassert -I[path] [cpptrace args] |
Para el marcador de posición [path] en -I[path] e /I[path] , especifique la ruta a la carpeta de incluir que contenga libassert/assert.hpp .
Si está vinculando estáticamente, también necesitará especificar -DLIBASSERT_STATIC_DEFINE .
Para el marcador de posición [cpptrace args] consulte la documentación de CPPTrace.
Libassert está disponible a través de Conan en https://conan.io/center/recipes/libassert.
[requires]
libassert/2.1.2
[generators]
CMakeDeps
CMakeToolchain
[layout]
cmake_layout
# ...
find_package (libassert REQUIRED)
# ...
target_link_libraries (YOUR_TARGET libassert::assert) vcpkg install libassert
find_package (libassert CONFIG REQUIRED)
target_link_libraries (YOUR_TARGET PRIVATE libassert::assert)Windows y MacOS requieren un poco de trabajo adicional para obtener todo en el lugar correcto
Copiar la biblioteca .dll en Windows:
# Copy the assert.dll on windows to the same directory as the executable for your_target.
# Not required if static linking.
if ( WIN32 )
add_custom_command (
TARGET your_target POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:libassert::assert>
$<TARGET_FILE_DIR:your_target>
)
endif ()En MacOS se recomienda generar un archivo DSYM que contenga información de depuración para su programa:
En xcode cmake esto se puede hacer con
set_target_properties (your_target PROPERTIES XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf-with-dsym" ) Y fuera de Xcode esto se puede hacer con dsymutil yourbinary :
# Create a .dSYM file on macos. Currently required, but hopefully not for long
if ( APPLE )
add_custom_command (
TARGET your_target
POST_BUILD
COMMAND dsymutil $<TARGET_FILE:your_target>
)
endif () Esta biblioteca no es un reemplazo de entrega de <cassert> . -DLIBASSERT_LOWERCASE se puede usar para crear alias en minúsculas para las macros de afirmación, pero tenga en cuenta que ASSERT de Libassert todavía se verifica en el lanzamiento. Para reemplazar <cassert> use con libassert, reemplace assert con DEBUG_ASSERT o crear un alias a lo largo de las siguientes líneas:
# define assert (...) DEBUG_ASSERT(__VA_ARGS__) Una cosa que debe ser consciente: anular assert de Cassert técnicamente no está permitido por el estándar, pero esto no debería ser un problema para ningún compilador sano.
No, todavía no.
cpp-sort de Morwenn Incluso con construcciones como assert_eq , a menudo faltan diagnósticos de afirmación. Por ejemplo, en el óxido se muestran los valores izquierdo y derecho, pero no las expresiones en sí mismas:
fn main ( ) {
let count = 4 ;
assert_eq ! ( count , 2 ) ;
} thread 'main' panicked at 'assertion failed: `(left == right)`
left: `4`,
right: `2`', /app/example.rs:3:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Esto no es tan útil como podría ser.
Funcionalidad Otros idiomas / sus bibliotecas estándar proporcionan:
| C/C ++ | Óxido | DO# | Java | Pitón | Javascript | Libassert | |
|---|---|---|---|---|---|---|---|
| Cadena de expresión | ✔️ | ✔️ | |||||
| Ubicación | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| Rastro de pila | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | |
| Mensaje de afirmación | ** | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| Diagnóstico adicional | * | * | * | * | ✔️ | ||
| Especializaciones binarias | ✔️ | ✔️ | ✔️ | ||||
| Descomposición de expresión automática | ✔️ | ||||||
| Cadenas de subexpresión | ✔️ |
* : Posible a través del formato de cadena pero eso es sub-ideal.
** : assert(expression && "message") se usa comúnmente, pero esto es sub-ideal y solo permite mensajes literarios de cadena.
Extras:
| C/C ++ | Óxido | DO# | Java | Pitón | Javascript | Libassert | |
|---|---|---|---|---|---|---|---|
| Destacación de sintaxis | ? | ✔️ | |||||
| Consistencia de formato literal | ✔️ | ||||||
| Cadenas de expresión y valores de expresión en todas partes | ✔️ | ||||||
| Valores de devolución de la afirmación para permitir que los afirmaciones se integren en expresiones en línea | ✔️ |