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

Static_assert - способ динамической настройки сообщения об ошибке

Есть ли способ, чтобы строка static_assert динамически настраивалась, а затем отображалась?
Я имею в виду что-то вроде:

//pseudo code
static_assert(Check_Range<T>::value, "Value of " + typeof(T) + " type is not so good ;)");
4b9b3361

Ответ 1

Нет, нет.

Однако это не имеет большого значения, потому что static_assert оцениваются во время компиляции, а в случае ошибки компилятор не только распечатает само сообщение, но также распечатает стек instanciation (в случае шаблоны).

Взгляните на этот синтетический пример в ideone:

#include <iostream>

template <typename T>
struct IsInteger { static bool const value = false; };

template <>
struct IsInteger<int> { static bool const value = true; };

template <typename T>
void DoSomething(T t) {
  static_assert(IsInteger<T>::value, // 11
  "not an integer");

  std::cout << t;
}

int main() {
  DoSomething("Hello, World!"); // 18
}

Компилятор не только испускает диагностику, но также испускает полный стек:

prog.cpp: In function 'void DoSomething(T) [with T = const char*]':
prog.cpp:18:30:   instantiated from here
prog.cpp:11:3: error: static assertion failed: "not an integer"

Если вы знаете Python или Java и как они печатают стек в случае исключения, он должен быть знаком. На самом деле это даже лучше, потому что вы не только получаете стек вызовов, но также получаете значения аргументов (типы здесь)!

Поэтому динамические сообщения не так необходимы:)

Ответ 2

Стандарт определяет второй аргумент static_assert как строковый литерал, поэтому нет возможности для вычисления там, насколько я могу видеть (кроме макросов препроцессора).

Компилятор может расширить стандарт и разрешить const-выражения соответствующего типа в этой позиции, но я понятия не имею, есть ли какой-либо компилятор.

Ответ 3

Как сказал Маттиу, это невозможно, но вы можете получить некоторые функции, которые вы ищете, используя макросы:

#define CHECK_TYPE_RANGE(type)\
    static_assert(Check_Range<type>::value, "Value of " #type " type is not so good ;)");

CHECK_TYPE_RANGE(float); // outputs "Value of float type is not so good ;)"