static_assert - способ динамически настраивать сообщение об ошибке - PullRequest
11 голосов
/ 15 октября 2011

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

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

Ответы [ 3 ]

10 голосов
/ 15 октября 2011

Нет, нет.

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

Посмотрите на этот синтетический пример в 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 и как они печатают стек в случае исключения, это должно быть знакомо.На самом деле, тем не менее, это даже лучше, потому что вы не только получаете стек вызовов, но вы также получаете значения аргументов (типы здесь)!

Следовательно, динамические сообщения не так необходимы:)

8 голосов
/ 15 октября 2011

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

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

1 голос
/ 20 ноября 2017

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

#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 ;)"
...