Как я могу реализовать макрос assert как метод? - PullRequest
1 голос
/ 25 августа 2011

Я хочу реализовать макрос assert как метод в C ++, например .NET Framewrk.

Например, в C # мы можем вызвать метод assert следующим образом:

Debug.Assert(index > -1);

и я хочу реализовать assert что-то вроде этого:

#include <assert.h>
class debug
{
  public:

    static void my_asset(<condition>) // like assert macro
    {
      // ?
    }
};

При использовании этого класса:

debug::my_asset(index > -1); // Actually should be called assert(index > -1);

Спасибо

Редактировать

Я хочу, чтобы при вызове debug::my_asset(index > -1); он отображал правильное имя файла и номер строки и работал как макрос ресурсов C ++.

Ответы [ 4 ]

6 голосов
/ 25 августа 2011

Есть несколько особенностей assert assert<assert.h> или <cassert>), которые представляют интерес:

  • что при компиляции сборки выпуска тесты assert вообще не оцениваются.
  • сообщение об ошибке, напечатанное при сбое подтверждения, может указать вам файл и номер строки, где ваше утверждение не удалось
  • он также может сообщить вам точный код ошибки.

Вы не можете сделать это в C ++ без использования макроса.

3 голосов
/ 25 августа 2011

Единственный способ получить номер строки, файл и текстовую версию - через макрос. Тем не менее:

#include <assert.h>
class debug
{
public:
    static void my_assert(bool passed, const char* assert, const char* file, long line)
    {
        if (passed == false)
            std::cout<<"failed assert "<<assert<<" in "<<file<<" at "<<line<<".\n";
    }
#ifdef NDEBUG
    #define myassert(x) my_assert(true, "", "", 0)
#else 
    #define myassert(x) my_assert(x, #x , __FILE__, __LINE__ )
#endif
};


int main() {
    debug::myassert(sizeof(int)==4);
    return 0,
}

Этот код работает странным образом. Первое x - это само выражение assert, которое оценивается как true или false, чтобы сказать my_assert, что делать. #x - волшебная команда препроцессора, которая делает версию x для char *, поэтому мы можем ее отобразить. __FILE__ заменяется именем файла, а __LINE__ заменяется номером строки. (Поскольку это макрос, он имеет тот же номер строки, что и вызывающая функция).

Когда вы набираете debug::myassert(sizeof(int)==4);, препроцессор говорит: «Я знаю, что такое myassert(whatever)!» и заменяет его. Таким образом, он заменяет все это на: debug::my_assert(sizeof(int)==4, "sizeof(int)==4", "main.cpp", 27);, которая является допустимой строкой кода. Так, например, если sizeof (int) равен 8 (это на некоторых машинах), первый параметр - false, и строка отображается как «fail assert sizeof (int) == 4 в main.cpp на 27».

2 голосов
/ 25 августа 2011

Вы могли бы

void debug::my_assert(bool cond) {
    ASSERT(cond);
}

Это работало бы так, что это вызвало бы исключение, когда утверждение не удалось.

Это немного менее полезно, чем макрос, потому что my_assert не можетпосмотрите, в каком состоянии произошел сбой - вы получите ошибку утверждения, но без полезного объяснения (хотя вы получите точную трассировку стека в отладчике).

Также посмотрите причины Кена, почему макрос болееполезно.

2 голосов
/ 25 августа 2011
static void my_asset(bool cond) // like assert macro
{
  ::assert(cond);
}

не работает?

...