c++ c++11 cout constexpr static-assert

std:: cout equivalente en tiempo de compilación, o static stassert stringification de valores constantes de tiempo de compilación en c++ 11



c++11 constexpr (1)

Citar la gramática dada para las declaraciones en §7 / 1 [dcl.dcl] :

static_assert-declaración:

static_assert (expresión-constante, cadena-literal);

El estándar dice que tiene que ser una cadena literal, por lo que está fuera de suerte; no puede usar una función constexpr para construir su mensaje de error.

Sin embargo, puede usar la magia del preprocesador que desee para generar una cadena literal para ingresar allí. Si PI_INT es #define en lugar de constexpr int , podría usar algo como esto:

#define PI_INT 4 #define pi_err_str_(x) #x #define pi_err_str(x) pi_err_str_(x) #define pi_int_err "PI_INT must be 3, not " pi_err_str(PI_INT) static_assert(PI_INT == 3, pi_int_err);

salida:

error: la aserción estática falló: "PI_INT debe ser 3, no 4"

Editar en respuesta al comentario de OP y pregunta actualizada

¿Hay una manera de escribir una macro que pueda generalizar esto para que pueda hacer algo como ... y obtener un mensaje de error que involucre a 4, de alguna manera?

Claro, un poco de magia de preprocesador puede generalizar eso, asumiendo que está contento de depender del comportamiento del mensaje de error específico del compilador:

#define strcat_(x, y) x ## y #define strcat(x, y) strcat_(x, y) #define PRINT_VALUE(x) template <int> struct strcat(strcat(value_of_, x), _is); static_assert(strcat(strcat(value_of_, x), _is)<x>::x, ""); constexpr int PI_INT = 4; PRINT_VALUE(PI_INT)

stackoverflow / 13465334.cpp: 20: 1: error: tipo incompleto ''value_of_PI_INT_is <4>'' usado en el especificador de nombre anidado

En cuanto a otros compiladores, no sé qué puede hacer de improviso, pero es posible que desee ver una copia del static_assert.hpp de boost para ver si alguno de los trucos empleados allí se puede utilizar para imprimir una plantilla evaluada.

¿Hay una manera de imprimir el valor de un valor constexpr o #define d en tiempo de compilación? Quiero el equivalente de std::cout << , o alguna forma de hacer algo como

constexpr int PI_INT = 4; static_assert(PI_INT == 3, const_str_join("PI_INT must be 3, not ", const_int_to_str(PI_INT)));

Edit: Puedo hacer una impresión básica en tiempo de compilación con constexpr s, al menos en gcc haciendo algo como

template <int v> struct display_non_zero_int_value; template <> struct display_non_zero_int_value<0> { static constexpr bool foo = true; }; static constexpr int v = 1; static_assert(v == 0 && display_non_zero_int_value<v>::foo, "v == 0");

lo que me da un error: incomplete type ''display_non_zero_int_value<1>'' used in nested name specifier static_assert(v == 0 && display_non_zero_int_value<v>::foo, "v == 0"); . (icpc, por otro lado, es menos útil, y solo dice error: incomplete type is not allowed ) ¿Hay una manera de escribir una macro que pueda generalizar esto para que pueda hacer algo como?

constexpr int PI_INT = 4; PRINT_VALUE(PI_INT)

y recibe un mensaje de error que involucra 4, de alguna manera?