Собственно, это логическое продолжение кода из ветки
В поисках семантической корректностиАвтор: Нахлобуч
Дата: 18.05.05
, а именно
Re[15]: В поисках семантической корректностиАвтор: CrystaX
Дата: 23.05.05
. Наконец у меня дошли руки до отделения зерен от плевел и вот результат.
Сам код будет в следующем сообщении, это всего один файл. Но вначале его возможности и пример использования. В примере использованы для демонстрации физические величины, выраженные в системах единиц СИ и СГС.
Возможности:
1. Независимые типы данных, такие как mass и length. Присвоить один другому нельзя — будет ошибка компиляции.
2. Автоматическое конвертирование величин одной и той же размерности из одной системы единиц в другую. К примеру, присвоив килограммам один грамм, в результирующей переменной (si::mass) обнаружим 0.001. Вычисление коэффициентов преобразования производится в compile time.
3. Контроль за корректностью формул со стороны компилятора. Так, если ускорению попытаться присвоить результат деления длины на время, возникнет ошибка компиляции. С моей точки зрения, это
наиболее важное свойство моего кода. Особенно это заметно на трехэтажных формулах, где очень легко потерять из виду, какая же в результате получается размерность. В случае использования моего кода подобного рода ошибки
полностью исключаются.
Пример:
#include <iostream>
#include <units.hpp>
using namespace units;
int main()
{
cgs::mass m1(1); // 1 грамм
si::mass m2(m1); // Автоматическое преобразование в килограммы. В результате получаем 0.001 кг
std::cout << "Mass in SI: " << m2 << ", in CGS: " << m1 << std::endl;
cgs::length l1(100); // 100 см
si::length l2(l1); // Автоматическое преобразование. Результат - 1 м
std::cout << "Length in SI: " << l2 << ", in CGS: " << l1 << std::endl;
cgs::time t1(1); // 1 с
si::time t2(t1); // Тоже 1 с, т.к. единицы измерения времени в системах СИ и СГС совпадают.
std::cout << "Time in SI: " << t2 << ", in CGS: " << t1 << std::endl;
// Теперь немного более сложный пример. Предыдущие величины (масса, длина, время) являются
// базовыми (ортами) в обеих системах единиц. Здесь же мы имеем дело с производными величинами -
// скоростью, енергией и мощностью
cgs::velocity v1(10); // 10 см/с
si::velocity v2(v1); // Результат преобразования - 0.1 м/с
std::cout << "Velocity in SI: " << v2 << ", in CGS: " << v1 << std::endl;
si::energy e1(0.0001); // 10e-4 Дж.
cgs::energy e2(e1); // e2 = 1000 эрг
std::cout << "Energy in SI: " << e1 << ", in CGS: " << e2 << std::endl;
// Это - пример работы с внесистемными единицами. В данном случае мощность переводится из ваттов
// в лошадиные силы
si::power p1(1000); // 1000 Вт
ext::power p2(p1); // 1.35962 лс
std::cout << "Power in SI: " << p1 << ", in Ext system: " << p2 << std::endl;
// Пример работы с простейшими арифметическими действиями
si::acceleration a1(1); // 1 м/с2
cgs::acceleration a2;
a2 = a1 + cgs::acceleration(200); // 1 м/с2 + 200 см/с2 = 300 см/с2, как и должно было быть
std::cout << "Acceleration: a1 = " << a1 << ", a2 = " << a2 << std::endl;
// Сила
si::force f1(10); // 10 Н
cgs::force f2 = f1*2; // 10 Н * 2 = 2000000 дин
si::force f3 = m1*l2/(t1*t1); // 1 г * 1 м / (1 с * 1 с) = 0.001 Н
// А вот так уже не скомпилируется - не та размерность
//si::force f4 = m1*l2/t1;
// Вот что выдает MS VC 7.1: error C2440: 'initializing' : cannot convert from
// 'units::unit<T,System,Tag>' to 'units::unit<T,System,Tag>'
// А вот что GCC 3.4.2 (mingw):
// test.cpp: In function `int main()':
// test.cpp:59: error: conversion from `units::unit<long double, units::helpers::systems::CGS,
// boost::mpl::vector<mpl_::int_<1>, mpl_::int_<1>, mpl_::int_<-0x000000001>, mpl_::int_<0>,
// mpl_::int_<0>, mpl_::int_<0>, mpl_::int_<0>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na,
// mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na> >'
// to non-scalar type `units::unit<long double, units::helpers::systems::SI, units::helpers::force_tag>'
// requested
std::cout << "Force: f1 = " << f1 << ", f2 = " << f2 << ", f3 = " << f3 << std::endl;
// Здесь ошибка компиляции - пытаемся складывать енергию, массу и скорость
//std::cout << "ERROR = " << (e1 + e2 + v1 + v2 + m1 + m2) << std::endl;
// Здесь происходит преобразование на лету. В результате имеем 0.0002 Дж - результат имеет тот же тип,
// что и левый операнд
std::cout << "Result = " << e1 + e2 << std::endl;
// Здесь выводится единица, т.к. e1 и e2 содержат одно и то же значение, но выраженное в разных
// системах единиц
std::cout << "Result = " << e1/e2 << std::endl;
return 0;
}
Исходники дальше.
... << RSDN@Home 1.1.4 stable rev. 510>>