Не могли бы вы привести пример, в котором static_assert(...)
('C ++ 11') элегантно решит поставленную задачу?
Я знаком с run-time assert(...)
. Когда я должен предпочесть static_assert(...)
обычному assert(...)
?
Кроме того, boost
там что-то называется BOOST_STATIC_ASSERT
, это то же самое, что и static_assert(...)
?
Ответы:
С верхней части моей головы...
Предполагая, что
SomeLibrary::Version
он объявлен как статическая константа, а не как#define
d (как можно было бы ожидать в библиотеке C ++).Сравните это с необходимостью компилировать
SomeLibrary
и код, связывать все и запускать исполняемый файл только тогда, чтобы узнать, что вы потратили 30 минут на компиляцию несовместимой версииSomeLibrary
.@Arak, в ответ на ваш комментарий: да, судя по всему, вы можете
static_assert
просто сидеть где угодно:источник
static_assert
контекст невыполнения? Кажется, это очень хороший пример :)static_assert
. Если условие не будет известно до запуска программы, используйтеassert
.Статическое утверждение используется для выполнения утверждений во время компиляции. Когда статическое утверждение терпит неудачу, программа просто не компилируется. Это полезно в различных ситуациях, например, если вы реализуете некоторые функции с помощью кода, который критически зависит от
unsigned int
объекта, имеющего ровно 32 бита. Вы можете поместить статическое утверждение, подобное этомув вашем коде. На другой платформе с
unsigned int
типом другого размера компиляция завершится ошибкой, что привлечет внимание разработчика к проблемной части кода и посоветует им повторно реализовать или повторно проверить ее.В другом примере вы можете передать какое-то целое значение в качестве
void *
указателя на функцию (хакер, но иногда полезно), и вы хотите убедиться, что целое значение поместится в указательВы можете захотеть актив, что
char
тип подписанили это целое деление с отрицательными значениями округляется до нуля
И так далее.
Утверждения времени выполнения во многих случаях могут использоваться вместо статических утверждений, но утверждения времени выполнения работают только во время выполнения и только тогда, когда управление передается над утверждением. По этой причине неудачное утверждение во время выполнения может бездействовать и оставаться незамеченным в течение длительных периодов времени.
Конечно, выражение в статическом утверждении должно быть константой времени компиляции. Это не может быть значением времени выполнения. Для значений времени выполнения у вас нет другого выбора, кроме как использовать обычные
assert
.источник
static_assert
конкретно ссылаться на C ++ 11. Моеstatic_assert
выше - это просто абстрактная реализация статического утверждения. (Я лично использую что-то подобное в коде C). Мой ответ предназначен для общего назначения статических утверждений и их отличий от утверждений времени выполнения.unsigned int
. Стандарт не гарантирует этого. Переменная типаunsigned int
может законно занимать 32 бита памяти, оставляя 16 из них неиспользованными (и, следовательно, макросUINT_MAX
будет равен65535
). Таким образом, то, как вы описываете первое статическое утверждение («unsigned int
объект, имеющий ровно 32 бита»), вводит в заблуждение. Для того, чтобы соответствовать вашему описанию, это утверждение должно быть включено , а также:static_assert(UINT_MAX >= 0xFFFFFFFFu)
.Я использую его, чтобы убедиться, что мои предположения о поведении компилятора, заголовках, библиотеках и даже моем собственном коде верны. Например, здесь я проверяю, что структура была правильно упакована до ожидаемого размера.
В классе обертке
stdio.h
«ыfseek()
, я принял некоторые ярлыки сenum Origin
и проверьте , что эти ярлыки совпадают с константами , определеннымиstdio.h
Вы должны отдавать предпочтение
static_assert
более ,assert
когда поведение определяется во время компиляции, а не во время выполнения, например, примеры я дал выше. Пример, когда это не так, может включать проверку параметров и кода возврата.BOOST_STATIC_ASSERT
- это макрос до C ++ 0x, который генерирует недопустимый код, если условие не выполняется. Намерения те же самые, хотяstatic_assert
стандартизированы и могут обеспечить лучшую диагностику компилятора.источник
BOOST_STATIC_ASSERT
это кроссплатформенная оболочка дляstatic_assert
функциональности.В настоящее время я использую static_assert, чтобы применить "Концепции" к классу.
пример:
Это вызовет ошибку времени компиляции, если любое из вышеперечисленных условий не будет выполнено.
источник
Одним из вариантов использования
static_assert
может быть обеспечение того, чтобы структура (то есть интерфейс с внешним миром, например сеть или файл) имела именно тот размер, который вы ожидаете. Это позволит выявить случаи, когда кто-то добавляет или изменяет член структуры, не осознавая последствий. Онstatic_assert
поднимет его и предупредит пользователя.источник
При отсутствии концептов можно использовать
static_assert
для простой и удобочитаемой проверки типов во время компиляции, например, в шаблонах:источник
Это не дает прямого ответа на исходный вопрос, но делает интересное исследование того, как обеспечить выполнение этих проверок времени компиляции до C ++ 11.
Глава 2 (раздел 2.1) « Современного дизайна на C ++» Андрея Александерску реализует эту идею утверждений времени компиляции, подобных этой.
Сравните макрос STATIC_CHECK () и static_assert ()
источник
static_assert
Может быть использован , чтобы запретить использованиеdelete
ключевого слова таким образом:#define delete static_assert(0, "The keyword \"delete\" is forbidden.");
Каждый современный разработчик C ++ может захотеть сделать это, если он или она хочет использовать консервативный сборщик мусора, используя только классы es и struct s, которые перегружают оператор new для вызова функции, которая выделяет память в консервативной куче консервативного сборщика мусора, который может быть инициализирован и создан путем вызова некоторой функции, которая делает это в начале
main
функции.Например, каждый современный разработчик C ++, который хочет использовать консервативный сборщик мусора Boehm-Demers-Weiser, в начале
main
функции напишет:GC_init();
И в каждом
class
иstruct
перегружатьoperator new
таким образом:И теперь, когда
operator delete
больше не требуется, поскольку консервативный сборщик мусора Бем-Демерс-Вайзер отвечает как за освобождение, так и за освобождение каждого блока памяти, когда он больше не нужен, разработчик хочет запретитьdelete
ключевое слово.Один из способов - перегрузить
delete operator
следующим образом:Но это не рекомендуется, потому что современный разработчик C ++ будет знать, что он / она по ошибке вызвал время
delete operator
выполнения, но лучше узнать это как можно скорее во время компиляции.Поэтому, на мой взгляд, лучшим решением этого сценария является использование того,
static_assert
что показано в начале этого ответа.Конечно, это тоже можно сделать с помощью
BOOST_STATIC_ASSERT
, но я думаю, чтоstatic_assert
это лучше и всегда следует отдавать предпочтение.источник