static_assert
Раз уж так много его обсуждаем, почему бы не рассказать о том, что это вообще такое.
Это фича С++11, которая позволяет прерывать компиляцию программы, если определенное условие не выполнено. Естественно, условие должно быть bool-constexpr выражением, иначе ничего не выйдет. static_assert на то и static, потому что работает во время компиляции. Рантайм выражения в это время не могут быть вычислены.
На данный момент доступны 2 вида этого ассерта:
static_assert(bool-constexpr, unevaluated-string)
static_assert(bool-constexpr)
Первая версия доступна с 11-х плюсов, вторая с 17-х. Первая добавляет к сообщению об ошибке вашу кастомную, но захардкоженую, строку для более полного и понятного контекста. Вторая такого поведения не предполагает, но оно и не всегда нужно.
Ну собственно, примеры вы уже видели. Хотя тут стоит сказать пару ласковых.
Мне кажется, что не стоит ставить ассерты на определенный тип шаблонных параметров шаблонных сущностей. Как верно указал Михаил в [этом комментарии](https://t.me/c/2009887601/2547), так будет сложно проверить на корректность перегрузку. Для такого рода ограничений лучше использовать концепты или sfinae. Единственное, что вы тогда потеряете вменяемое сообщение об ошибке и возможность его дополнить своим сообщением.
Статический ассерт может быть удобен для проверки размера структуры, которая взаимодействует с внешним миром. Например, низкоуровневый сетевой код может полагаться на один размер структуры, и какой-то нерадивый человек внес изменения в эту структуру и изменил ее размер без изменения всего связанного кода. Тогда возможны очень трудноотловимые ошибки. Этого можно избежать, поставив простой ассерт на размер этой структуры. И если размер вдруг изменится, то компиляция просто прервется. Тоже самое можно проводить и с размерами базовых типов. Правда тут возможно придется со всякими паддингами повозиться(эффективный рэндж беззнакового инта может быть [0, 65тыщ_что-то_там], а в памяти он будет занимать будет 4 байта).
Можно также проверять версию подключаемых библиотек, если они предоставляют свою версию в виде constexpr выражения, а не макроса(хотя это довольно редкое явление). Типа такого:
Ну и вообще, любые предположения о вашем коде, которые вы можете проверить в compile-time, стоит обернуть в эту конструкцию. Так вы убережете себя от долгих и бессмысленных сборок проектов, трудноотловимых багов и прочего. В общем, штука крутая.
Check your assumptions in advance. Stay cool.
#cpp11 #cpp17 #compiler
Раз уж так много его обсуждаем, почему бы не рассказать о том, что это вообще такое.
Это фича С++11, которая позволяет прерывать компиляцию программы, если определенное условие не выполнено. Естественно, условие должно быть bool-constexpr выражением, иначе ничего не выйдет. static_assert на то и static, потому что работает во время компиляции. Рантайм выражения в это время не могут быть вычислены.
На данный момент доступны 2 вида этого ассерта:
static_assert(bool-constexpr, unevaluated-string)
static_assert(bool-constexpr)
Первая версия доступна с 11-х плюсов, вторая с 17-х. Первая добавляет к сообщению об ошибке вашу кастомную, но захардкоженую, строку для более полного и понятного контекста. Вторая такого поведения не предполагает, но оно и не всегда нужно.
Ну собственно, примеры вы уже видели. Хотя тут стоит сказать пару ласковых.
Мне кажется, что не стоит ставить ассерты на определенный тип шаблонных параметров шаблонных сущностей. Как верно указал Михаил в [этом комментарии](https://t.me/c/2009887601/2547), так будет сложно проверить на корректность перегрузку. Для такого рода ограничений лучше использовать концепты или sfinae. Единственное, что вы тогда потеряете вменяемое сообщение об ошибке и возможность его дополнить своим сообщением.
Статический ассерт может быть удобен для проверки размера структуры, которая взаимодействует с внешним миром. Например, низкоуровневый сетевой код может полагаться на один размер структуры, и какой-то нерадивый человек внес изменения в эту структуру и изменил ее размер без изменения всего связанного кода. Тогда возможны очень трудноотловимые ошибки. Этого можно избежать, поставив простой ассерт на размер этой структуры. И если размер вдруг изменится, то компиляция просто прервется. Тоже самое можно проводить и с размерами базовых типов. Правда тут возможно придется со всякими паддингами повозиться(эффективный рэндж беззнакового инта может быть [0, 65тыщ_что-то_там], а в памяти он будет занимать будет 4 байта).
Можно также проверять версию подключаемых библиотек, если они предоставляют свою версию в виде constexpr выражения, а не макроса(хотя это довольно редкое явление). Типа такого:
#include "SomeVeryC++ishLibrary.hpp"
static_assert(SomeVeryC++ishLibrary.::Version > 2,
"Old versions of SomeVeryC++ishLibrary. are missing functionality to destroy the world.
It is very desired functionality so cannot process!");
class DestroyTheWorld {
// BOOM!!
};
Ну и вообще, любые предположения о вашем коде, которые вы можете проверить в compile-time, стоит обернуть в эту конструкцию. Так вы убережете себя от долгих и бессмысленных сборок проектов, трудноотловимых багов и прочего. В общем, штука крутая.
Check your assumptions in advance. Stay cool.
#cpp11 #cpp17 #compiler