Comments 10
В c++ бывает очень удобно все переменные всегда хранить в СИ, а для удобства ввода и читаемости кода использовать User-defined literals:
Те же самые user-defined literals очень удобно использовать при работе с комплексными числами, кватернионами, трехмерными векторами, датами и прочей структурированной информацией.
long double operator "" _feet(long double d)
{
return d * 0.3048;
}
auto meter = 3.28084_feet;
std::cout << meter << std::endl; // prints 1.0
Те же самые user-defined literals очень удобно использовать при работе с комплексными числами, кватернионами, трехмерными векторами, датами и прочей структурированной информацией.
Я был бы не против, если бы всё хранилось в СИ, но тут проблема другая — данные хранятся в разных единицах и нужно избежать ошибок конвертации. Самое банальное — забыл конвертировать, и сложил метры с миллиметрами.
Так реализуйте все вычисления в СИ. Конструкторы замените методами типа Length.FromMeters(...), Length.FromInches(), снаружи вычисления везде производите не с непонятными double и int, а с Length. Ну и собственно при необходимости отобразить где-то значение в виде конкретной единицы реализуйте get-методы типа Meters(), Millimeters(). Подобным образом реализован TimeSpan в C#, и как выяснилось чуть позже — TTimeSpan в Delphi.
Ладно еще если метры с миллиметрами где-то перепутал. Перегрузка операторов помогает — можно райзить эксепшн при попытке каста, или конвертировать и хранить всё в СИ.
А если вот где-то ускорение в метрах за секунду в квадрате суммируется с метрами?
Получается что в перегрузке операторов нужно перечислить все возможные типы, в которые оно может кастится.
Жаль, что нельзя принудительно сказать компилятору что эти типы не кастятся, или хотя бы ворнинг выводить.
А если вот где-то ускорение в метрах за секунду в квадрате суммируется с метрами?
Получается что в перегрузке операторов нужно перечислить все возможные типы, в которые оно может кастится.
Жаль, что нельзя принудительно сказать компилятору что эти типы не кастятся, или хотя бы ворнинг выводить.
Зачем хранить в разных единицах? На входе преобразовать в одну. На выходе в другую.
Единственный случай когда используются данные сильно разных порядков (т.е. к диаметру Земли прибавить диаметр атома), но такие вычисления часто бессмысленны.
Если не хотите переводить метры в миллиметры, просто не пишите оператор приведения. При попытке одновременной работы вас проверит компилятор, иначе вычисления могут(обязательно) прерваться на последнем этапе.
Единственный случай когда используются данные сильно разных порядков (т.е. к диаметру Земли прибавить диаметр атома), но такие вычисления часто бессмысленны.
Если не хотите переводить метры в миллиметры, просто не пишите оператор приведения. При попытке одновременной работы вас проверит компилятор, иначе вычисления могут(обязательно) прерваться на последнем этапе.
Немного из альтернативной вселенной, просто от нечего делать:
type time is range -2147483647 to 2147483647
units
fs;
ps = 1000 fs;
ns = 1000 ps;
us = 1000 ns;
ms = 1000 us;
sec = 1000 ms;
min = 60 sec;
hr = 60 min;
end units;
Вы производительность такого кода тестировали? Потому что оверхед при перегрузках там есть, и даже с inline-ом. Просто не прикольно, когда сложение двух чисел начинает работать в 8 раз медленнее.
Sign up to leave a comment.
Работа с разными единицами измерения одинакового типа и их конвертация