Pull to refresh

Comments 13

Статическая проверка очень полезна, я только за её использование. Сам использую реализацию от Александреску.
Способ Александреску идет в контексте использования шаблонов, как пример реализации static_assert с их помощью. Способ автора лично мне кажется более наглядным.
Макросы это не проверка на этапе компиляции. Это проверка на этапе препроцессинга. Любой человек который работал с макросами в большом проекте знает какой это геморрой. Я тут имею в виду не потенциальную опасность макросов (про это столько уже сказано что повторяться нет смысла), я имею в виду дебаг.

Иными словами, зачем писать макрос assert если есть буст? Там кстати макрос лишь обертка для проверки темплейтом. Если в проекте нет буста (и нет С++11) темплейт можно написать самому — там всего-то две строчки.
Честно говоря, не вижу разницы, каким способом заставить компилятор выдать ошибку (boost и новый стандарт упомянуты).
Способ с шаблонами описан по ссылке на stackoverflow, но выглядит менее лаконичным в применении, имхо.
Предлагается такой полуавтоматический способ решения — заводим в классе константу версии данных:
class MyData {
static const int DataVersion = 0;

};
Теперь во всех методах, в которых важно отследить целостность всех данных, можно прописать:
ASSERT(DataVersion == 0);

Как вариант вместо DataVersion использовать sizeof(MyData). Получается автоматически, но может не отловить одновременное удаление старых и добавление новых членов данных с одинаковым суммарным размером.
А ещё выравнивание, а ещё unicode/ansii и прочие «ой, добавили виртуальный метод». Я бы не стал так делать, это перегиб в другую сторону — менять константу придётся чаще и не всегда по делу (при портировании, например).

По поводу «добавили+удалили» — такие же изменения в enum'е можно и не отловить, лучше просто разносить правки (добавили что-то, собрали, исправили, удалили что-то и т.д.).
Вы правильно написали, что default лучше не использовать, так как при добавлении нового значения в enum компилятор(gcc) выдаёт предупреждение, что новое значение не используется в switch-case, многие это упускают из виду.
Ещё хотелось бы напомнить, что с недавнего времени модно длину массивов стало определять через хромовский макрос:
template <typename T, size_t N>
char (&ArraySizeHelper(T (&array)[N]))[N];
#define ARRAY_SIZE(array) (sizeof(ArraySizeHelper(array)))

или в более читабельном варианте:
template <typename T, size_t N>
typename boost::add_reference<char[N]>::type ArraySizeHelper( T (&)[N] ) ;
#define ARRAY_SIZE(array) (sizeof(ArraySizeHelper(array)))

это исключает возможность использования макроса для произвольного указателя.
Спасибо, полезное замечание.
Обновил пост и попробую внедрить такой вариант у себя.
Примерно такая же реализация макроса _countof в Visual C++ (http://msdn.microsoft.com/en-us/library/ms175773(v=vs.80).aspx)
Какие костыли приходится придумывать, когда нет нормальной среды.
Зато этот «костыль» будет работать на всех компиляторах и, тем более, средах.
Вот здесь, кратко про static_assert в C++11, штука однозначно полезная!
Sign up to leave a comment.

Articles