Что static_assert делает, и для чего Вы использовали бы его?

Вы могли дать пример где static_assert(...) ('C++ 11'), решил бы проблему в руке изящно?

Я знаком со временем выполнения assert(...). Когда должен я предпочитать static_assert(...) по постоянному клиенту assert(...)?

Кроме того, в boost существует что-то позвонившее BOOST_STATIC_ASSERT, действительно ли это - то же как static_assert(...)?

109
задан Pharap 10 September 2019 в 06:52
поделиться

4 ответа

С ума сойти ...

#include "SomeLibrary.h"

static_assert(SomeLibrary::Version > 2, 
         "Old versions of SomeLibrary are missing the foo functionality.  Cannot proceed!");

class UsingSomeLibrary {
   // ...
};

Предполагая, что SomeLibrary :: Version объявлен как статическая константа, а не как #define d (как и следовало ожидать от библиотеки C ++).

В отличие от фактической компиляции SomeLibrary и вашего кода, связывания всего и запуска только исполняемого файла , затем для узнайте, что вы потратили 30 минут на компиляцию несовместимой версии SomeLibrary .

@Arak, в ответ на ваш комментарий: да, вы можете иметь static_assert , просто сидя где угодно, откуда его внешний вид:

class Foo
{
    public: 
        static const int bar = 3;
};

static_assert(Foo::bar > 4, "Foo::bar is too small :(");

int main()
{ 
    return Foo::bar;
}
$ g++ --std=c++0x a.cpp
a.cpp:7: error: static assertion failed: "Foo::bar is too small :("
76
ответ дан 24 November 2019 в 03:21
поделиться

Я использую его, чтобы убедиться, что мои предположения о поведении компилятора, заголовках, библиотеках и даже моем собственном коде верны. Например, здесь я проверяю, что структура была правильно упакована до ожидаемого размера.

struct LogicalBlockAddress
{
#pragma pack(push, 1)
    Uint32 logicalBlockNumber;
    Uint16 partitionReferenceNumber;
#pragma pack(pop)
};
BOOST_STATIC_ASSERT(sizeof(LogicalBlockAddress) == 6);

В классе, обертывающем stdio.h fseek () , я использовал несколько сокращений с помощью enum Origin и убедитесь, что эти ярлыки соответствуют константам, определенным в stdio.h

uint64_t BasicFile::seek(int64_t offset, enum Origin origin)
{
    BOOST_STATIC_ASSERT(SEEK_SET == Origin::SET);

. Вы должны предпочесть static_assert , а не assert , когда поведение определяется во время компиляции, а не во время выполнения, как в приведенных выше примерах. Пример, где это , а не , случай будет включать проверку параметров и кода возврата.

BOOST_STATIC_ASSERT - это макрос до C ++ 0x, который генерирует недопустимый код, если условие не выполняется. Намерения те же самые, хотя static_assert стандартизирован и может обеспечить лучшую диагностику компилятора.

12
ответ дан 24 November 2019 в 03:21
поделиться

Статическое утверждение используется для выполнения утверждений во время компиляции. Когда статическое утверждение терпит неудачу, программа просто не компилируется. Это полезно в различных ситуациях, например, если вы реализуете некоторые функции с помощью кода, который критически зависит от объекта unsigned int , имеющего ровно 32 бита. Вы можете поместить в свой код статическое утверждение вроде этого

static_assert(sizeof(unsigned int) * CHAR_BIT == 32);

. На другой платформе с типом unsigned int другого размера компиляция завершится неудачно, что привлечет внимание разработчика к проблемной части кода и посоветует им повторно реализовать или повторно проверить ее.

В качестве другого примера вы можете захотеть передать некоторое целое значение как указатель void * на функцию (хак, но иногда полезно), и вы хотите убедиться, что целое значение поместится в указатель

int i;

static_assert(sizeof(void *) >= sizeof i);
foo((void *) i);

. Возможно, вы захотите активировать, что тип char подписан

static_assert(CHAR_MIN < 0);

или это целое деление с округлением отрицательных значений в сторону нуля

static_assert(-5 / 2 == -2);

И т. д.

Утверждения времени выполнения во многих случаях могут использоваться вместо статических утверждений, но утверждения времени выполнения работают только во время выполнения и только тогда, когда управление передается над утверждением. По этой причине неудачное утверждение во время выполнения может оставаться бездействующим, необнаруженным в течение продолжительных периодов времени.

Конечно, выражение в статическом утверждении должно быть константой времени компиляции. Это не может быть значением времени выполнения. Для значений времени выполнения у вас нет другого выбора, кроме как использовать обычный assert .

но утверждения во время выполнения работают только во время выполнения и только тогда, когда управление передается через утверждение. По этой причине неудачное утверждение во время выполнения может оставаться бездействующим, незамеченным в течение продолжительных периодов времени.

Конечно, выражение в статическом утверждении должно быть константой времени компиляции. Это не может быть значением времени выполнения. Для значений времени выполнения у вас нет другого выбора, кроме как использовать обычный assert .

но утверждения во время выполнения работают только во время выполнения и только тогда, когда управление передается через утверждение. По этой причине неудачное утверждение во время выполнения может оставаться бездействующим, необнаруженным в течение продолжительных периодов времени.

Конечно, выражение в статическом утверждении должно быть константой времени компиляции. Это не может быть значением времени выполнения. Для значений времени выполнения у вас нет другого выбора, кроме как использовать обычный assert .

125
ответ дан 24 November 2019 в 03:21
поделиться

Одно использование static_assert может гарантировать, что структура (то есть интерфейс с внешним миром, например сеть или файл) имеет именно тот размер, который вы ожидаете. Это позволит выявить случаи, когда кто-то добавляет или изменяет член структуры, не осознавая последствий. static_assert поднимет его и предупредит пользователя.

Это позволит выявить случаи, когда кто-то добавляет или изменяет член структуры, не осознавая последствий. static_assert поднимет его и предупредит пользователя.

Это позволит выявить случаи, когда кто-то добавляет или изменяет член структуры, не осознавая последствий. static_assert поднимет его и предупредит пользователя.

7
ответ дан 24 November 2019 в 03:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: