Evgenii Legotckoi
02 січня 2018 р. 15:33

C++ - Підручник 012. static_assert, перевірка помилок під час компіляції

Винятки викидаються під час виконання програми, якщо помилка може бути знайдена під час компіляції програми, то можна використовувати static_assert , який повідомить про необхідність поправити програмний код у ключових місцях.

Використання static_assert буде виглядати наступним чином.

static_assert(4<=sizeof(int), "integers are too small"); // проверка размера integer

Синтаксис буде наступним static_assert(A, B); де

  • A - це умова, за якої викидатиметься помилка в тому випадку, якщо A дорівнює false
  • B - це текст повідомлення про помилку

Застосування

static_assert може бути корисним при використанні констант та константних виразів, які обчислюються на етапі компіляції.

У цьому коді проводиться перевірка локальної константної швидкості, яка не може бути швидше за швидкість світла.

constexpr double C = 299792.458; // km/s, скорость света

void f(double speed)
{
    const double local_max = 160.0/(60∗60); // 160 km/h == 160.0/(60*60) km/s
    static_assert(speed<C,"can't go that fast"); // error: speed должна быть константой
    static_assert(local_max<C,"не может двигаться быстрее"); // OK
}

Також можна використовувати цю перевірку в ключових місцях для перерахувань. Наприклад, дано такий перелік.

enum Types
{
    E_BEGIN_TYPES,
        E_A = E_BEGIN_TYPES,
        E_B,
        E_C,
        E_D,
    E_END_TYPES = E_D
};

І є наступний метод чи функція в якомусь місці коду

QString getStandardMessage(Types type)
{
    static_assert(E_END_TYPES == 3, "Need to implement method for new type");

    switch (type)
    {
        case E_A: return "Type A";
        case E_B: return "Type B";
        case E_C: return "Type C";
        case E_D: return "Type D";
        default: return "Type is not implemented";
    }
}

В даному випадку ми знаємо, що останні перерахування, тобто E_D або E_END_TYPES дорівнюватимуть 3. І виняток під час компіляції викинуто не буде. Але як тільки буде додано новий учасник цього переліку.

enum Types
{
    E_BEGIN_TYPES,
        E_A = E_BEGIN_TYPES,
        E_B,
        E_C,
        E_D,
        E_E, // Новый участник перечисления
    E_END_TYPES = E_E
};

То static_assert викине помилку, яка означатиме, що ми забули виправити цей метод. Виправлення буде виглядати так.

QString getStandardMessage(Types type)
{
    static_assert(E_END_TYPES == 4, "Need to implement method for new type");

    switch (type)
    {
        case E_A: return "Type A";
        case E_B: return "Type B";
        case E_C: return "Type C";
        case E_D: return "Type D";
        case E_E: return "Type E";
        default: return "Type is not implemented";
    }
}

У цьому методі ми додамо реалізацію коду типу E_E, і навіть поправимо сам static_assert, щоб він враховував кількість учасників перерахування з новим учасником.

Рекомендовані статті на цю тему

По статті запитували0питання

1

Вам це подобається? Поділіться в соціальних мережах!

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up