Подтвердить что ты не робот

Std:: cout эквивалент во время компиляции или static_assert строкой значений констант времени компиляции в С++ 11

Есть ли способ распечатать значение значения 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 s, по крайней мере, на 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, каким-то образом?

4b9b3361

Ответ 1

Цитирование грамматики, заданной для объявлений в §7/​​1 [dcl.dcl]:

static_assert-declaration:

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"


Изменить в ответ на комментарий OP и обновленный вопрос

Есть ли способ написать макрос, который может обобщить это, чтобы я мог сделать что-то вроде... и получить сообщение об ошибке, которое связано с 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 > , используемый в спецификаторе вложенных имен

Как и для других компиляторов, я не знаю, что вы можете делать без дела, но вы можете посмотреть на копию boost static_assert.hpp, чтобы узнать, можно ли использовать любой из трюков, используемых там, чтобы получить оцениваемый шаблон arg.