среда, 15 июля 2015 г.

Дебажим компиляцию

Представте себе ситуацию... Пишется обобщённый код на C++, в зависимости от шаблонного типа или типов выводятся типы каких-то внутренних переменных или дочерних типов, используя для этого как стандартные трансформаторы типов из type_traits, так и самописные. И вот, в результате система ведёт себя так, будто финальный тип оказался не таким как ожидалось. Я, разумеется, имею в виду ситуацию когда код скомпилировался в режиме -Wall -Werror. Как бы на этапе компиляции посмотреть что кого? Выход есть и он прост:

template<typename T>
void dbgtype(T) {
  static_assert(std::is_same<void, T>::value, "!!!");
}

Позвав такую функцию и передав туда экземпляр типа который получился после всех трансформаций, мы развалим компиляцию и в сообщениях об ошибке будет развёрнута полная специализация этой шаблонной функи. В том числе в вывод попадёт и тип T который нас интересует.

З.Ы. Эта шутка здорово сегодя помогла, когда я писал кое какие геометрические алгоритмы которые должны работать как числами с плавающими точками (координаты в проекции географических данных на плоскость), так и с целочисленными типами (экранные координаты в пикселях). Для целочисленных типов мне нужно было найти соответствующий им беззнаковый тип, под размеры областей, а для чисел с плавающей точкой требовалось использовать немодифицированный тип. std::make_unsigned делал для меня первую часть задачи правильно, но не компилился для double, пришлось его дорабоать, а потом поискать баги в том что получилось.