Есть ли способ добавить или отредактировать сообщение, созданное assert? Я бы хотел использовать что-то вроде
assert(a == b, "A must be equal to B");
Затем компилятор добавляет строку, время и так далее ...
Является ли это возможным?
Есть ли способ добавить или отредактировать сообщение, созданное assert? Я бы хотел использовать что-то вроде
assert(a == b, "A must be equal to B");
Затем компилятор добавляет строку, время и так далее ...
Является ли это возможным?
Хакер, который я видел, - это использование оператора &&
. Поскольку указатель "истинен", если он не равен нулю, вы можете сделать следующее, не изменяя условия:
assert(a == b && "A is not equal to B");
Поскольку assert
показывает невыполненное условие, оно также отобразит ваше сообщение. Если этого недостаточно, вы можете написать свою собственную myAssert
функцию или макрос, который будет отображать все, что вы хотите.
assert(("A must be equal to B", a == b));
- person Keith Thompson; 08.01.2012
assert(a == b && "A (" << A << ") is not equal to B (" << B << ")");
- person Frank; 03.07.2013
printf
возвращает ненулевое значение, если он что-то напечатал, поэтому вы можете сделать что-то вроде assert(a == b && printf("a (%i) is not equal to b (%i)", a, b))
, хотя в этот момент вам, вероятно, следует написать свою собственную оболочку assert.
- person zneak; 04.07.2013
assert
печатает всю строку assert
в случае сбоя.
- person zneak; 07.11.2014
assert
у меня не работает, я использую `Assert :: AreEqual (2, HelloWorld :: getTwo ());` можно ли применить аналогичный принцип к этому синтаксису?
- person Wakan Tanka; 26.10.2016
a == b && "foo"
совпадает с a == b
. Если ваш код сам не выполняет этого сравнения, вы не сможете этого сделать.
- person zneak; 27.10.2016
assert(a==b ||(0&&"A is not equal to B"));
не было бы лучше, поскольку это позволяет программе не оценивать строку каждый раз, когда она проходит через assert?
- person TUI lover; 09.08.2019
Другой вариант - поменять местами операнды и использовать оператор запятой. Вам нужны дополнительные круглые скобки, чтобы запятая не рассматривалась как разделитель между аргументами:
assert(("A must be equal to B", a == b));
(это было скопировано из приведенных выше комментариев для лучшей наглядности)
#define m_assert(expr, msg) assert(( (void)(msg), (expr) ))
- person Jander; 24.09.2018
Вот моя версия макроса assert, который принимает сообщение и распечатывает все в понятной форме:
#include <iostream>
#ifndef NDEBUG
# define M_Assert(Expr, Msg) \
__M_Assert(#Expr, Expr, __FILE__, __LINE__, Msg)
#else
# define M_Assert(Expr, Msg) ;
#endif
void __M_Assert(const char* expr_str, bool expr, const char* file, int line, const char* msg)
{
if (!expr)
{
std::cerr << "Assert failed:\t" << msg << "\n"
<< "Expected:\t" << expr_str << "\n"
<< "Source:\t\t" << file << ", line " << line << "\n";
abort();
}
}
Теперь вы можете использовать это
M_Assert(ptr != nullptr, "MyFunction: requires non-null argument");
А в случае сбоя вы получите такое сообщение:
Ошибка утверждения: MyFunction: требуется ненулевой аргумент
Ожидается: ptr! = Nullptr
Источник: C: \ MyProject \ src.cpp, строка 22
Красиво и чисто, не стесняйтесь использовать это в своем коде =)
x == y
. Затем Expr расширится до if( !(x == y))
, и здесь проверяется условие, а #Expr расширится до строкового литерала "x == y"
, который мы затем поместим в сообщение об ошибке.
- person Eugene Magdalits; 14.10.2016
BOOST_ASSERT_MSG(expre, msg)
http://www.boost.org/doc/libs/1_51_0/libs/utility/assert.html
Вы можете использовать это напрямую или скопировать код Boost. Также обратите внимание, что утверждение Boost - это только заголовок, поэтому вы можете просто взять этот единственный файл, если не хотите устанавливать все Boost.
Поскольку ответ zneak несколько запутывает код, лучший подход - просто прокомментировать строковый текст, о котором вы говорите. т.е.:
assert(a == b); // A must be equal to B
Поскольку читатель ошибки assert все равно будет искать файл и строку из сообщения об ошибке, они увидят здесь полное объяснение.
Потому что, в конце концов, это:
assert(number_of_frames != 0); // Has frames to update
читается лучше, чем это:
assert(number_of_frames != 0 && "Has frames to update");
с точки зрения человеческого анализа кода, т.е. читаемость. Также не языковой взлом.
assert - это комбинация макроса / функции. вы можете определить свой собственный макрос / функцию, используя __FILE__
, __BASE_FILE__
, __LINE__
и т. д., с вашей собственной функцией, которая принимает настраиваемое сообщение
Если утверждение выполняется внутри класса, альтернативным подходом является вызов функции статического предиката с самоописывающимся именем. Если утверждение не выполняется, сообщение уже будет содержать красивое и самоописывающее имя предиката.
E.g.:
static bool arguments_must_be_ordered(int a, int b) {return a <= b;}
void foo(int a, int b)
{
assert(arguments_must_be_ordered(a, b));
// ...
}
Вы даже можете сделать эту функцию предиката общедоступной, чтобы пользователь класса мог сам проверить предварительное условие.
Даже если assert
не отключен для сборок выпуска, компилятор, скорее всего, встроит предикат, если он довольно тривиален.
Тот же подход можно использовать для сложных if
условий, требующих комментария. Вместо комментария просто вызовите функцию предиката с самоописанием.
Вы также можете просто написать свою собственную функцию утверждения. Очень простой пример:
bool print_if_false(const bool assertion, const char* msg) {
if(!assertion) {
// endl to flush
std::cout << msg << std::endl;
}
return assertion;
}
int main()
{
int i = 0;
int j = 1;
assert(print_if_false(i == j, "i and j should be equal"));
return 0;
}
Утверждение читается как Assertion print_if_false(i == j, "i and j should be equal")
.
Для vc добавьте следующий код в assert.h,
#define assert2(_Expression, _Msg) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Msg), _CRT_WIDE(__FILE__), __LINE__), 0) )