Я управляю преобразованием единиц измерения. Скажите нам, что я достиг состояния, когда я этого достиг.
Сердцем моего преобразования между различными единицами измерения является следующая общая функция шаблона:
template <class SrcUnit, class TgtUnit> extern
double convert(double val);
Цель этой функции — преобразовать физическую величину, выраженную в единицах типа SrcUnit
, в другую, выраженную в единицах типа TgtUnit
.
У меня есть класс Quantity<Unit>
, который управляет значениями и их единством, и этот класс пытается обеспечить безопасность типов и автоматическое преобразование. Например, я экспортирую следующий конструктор:
template <class SrcUnit>
Quantity(const Quantity<SrcUnit> & q)
: unit(UnitName::get_instance())
{
check_physical_units(q); // verify that the physical magnitudes are the same
value = convert<SrcUnit, UnitName>(q.value); // <<- here the conversion is done
check_value(); // check if the value is between the allowed interval
}
Я экспортирую другие вещи, где выполняется преобразование.
Итак, когда кто-то хочет управлять новым юнитом, он указывает новый производный класс Unit
. Я добиваюсь этого, помещая в макрос всю необходимую спецификацию нового класса. Теперь ответственность за написание функций преобразования лежит на этом пользователе. То есть написать две специализации шаблона convert()
. Например, предположим, что у вас есть единица измерения под названием «Kilometerand you wish to specify a new unit called
Mile». В этом случае вы делаете следующее:
Declare_Unit(Mile, "mi", "English unit of length", Distance,
0, numeric_limits<double>::max()); // macro instantiating a new Unit class
template <> double convert<Kilometer, Mile>(double val) { return val/1609.344; }
template <> double convert<Mile, Kilometer>(double val) { return 1609.344*val; }
Что произойдет, если пользователь забудет написать функцию преобразования? Что ж, в этом случае компоновщик потерпит неудачу, потому что не сможет найти специализацию convert()
.
Теперь мой вопрос.
Хотя я думаю, что ошибка компоновщика допустима в качестве поведения для сообщения пользователю об отсутствующем convert()
, я хотел бы проверить время компиляции на наличие специализации convert()
. Итак, мой вопрос: как я могу этого добиться? Я предполагаю, что через static_assert
помещается непосредственно перед каждым вызовом convert()
, который проверяет, известна ли уже специализация. Но как это сделать?
PS: Кроме того, мне было бы очень полезно, если бы кто-нибудь порекомендовал мне хороший текст о метапрограммировании C++.
N^2
функции преобразования? Вам нужно реализовать оба отKilometer
доMile
и отMile
доKilometer
по отдельности? - person Barry   schedule 28.07.2016N^2
, тогда да, @Barry. И по второму вопросу тоже да. Обратите внимание, что бывают случаи, когда преобразование не является строго линейным; хотя это может показаться странным, это относится к некоторым геологическим корреляциям, когда преобразование может быть действительным только внутри эмпирически достоверного интервала. Включительно, есть ситуации, в которых преобразование разрешено только в одном смысле. В любом случае, любые предложения по дизайну очень приветствуются - person lrleon   schedule 28.07.2016N^2
, так это то, что если у вас естьN
единиц, то каждая единица нуждается в своей собственной функции преобразования в каждую другую единицу... так что у вас естьN^2
различных функций преобразования. Это... не очень хорошо масштабируется. - person Barry   schedule 28.07.2016