Есть ли способ напечатать значение constexpr
или же #define
значение d во время компиляции? Я хочу эквивалент std::cout <<
или какой-то способ сделать что-то вроде
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)));
Редактировать: Я могу сделать некоторую основную печать во время компиляции с constexpr
с, по крайней мере на GCC, делая что-то вроде
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");
что дает мне 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, с другой стороны, менее полезен, и просто говорит error: incomplete type is not allowed
) Есть ли способ написать макрос, который может обобщить это так, чтобы я мог сделать что-то вроде
constexpr int PI_INT = 4;
PRINT_VALUE(PI_INT)
и получить сообщение об ошибке, которое включает 4, как-нибудь?
Цитируя грамматику, приведенную для объявлений в §7 / 1 [dcl.dcl]:
static_assert-заявление:
static_assert
(константное выражение, строковый литерал);
Стандарт гласит, что это должен быть строковый литерал, так что вам не повезло; Вы не можете использовать функцию constexpr для создания вашего сообщения об ошибке.
Однако вы можете использовать любую магию препроцессора, которая вам нравится, чтобы сгенерировать строковый литерал, чтобы идти туда. Если PI_INT
это #define вместо constexpr int
, вы можете использовать что-то вроде этого:
#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);
выход:
ошибка: статическое утверждение не удалось: «PI_INT должно быть 3, а не 4»
редактировать в ответ на комментарий ОП и обновленный вопрос
Есть ли способ написать макрос, который может обобщить это так, чтобы я мог сделать что-то вроде … и получить сообщение об ошибке, которое включает 4, каким-то образом?
Конечно, немного магии препроцессора может обобщить это, предполагая, что вы счастливы полагаться на поведение сообщений об ошибках, специфичное для компилятора:
#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: ошибка: неполный тип ‘value_of_PI_INT_is<4> ’используется в описателе вложенного имени
Что касается других компиляторов, я не знаю, что вы можете сделать вручную, но вы можете взглянуть на копию файла static_assert.hpp boost и посмотреть, можно ли использовать какие-либо приемы, используемые там, для печати оцененного аргумента шаблона.
Других решений пока нет …