LINUX.ORG.RU

Типы для физических величин на C++: поругайте

 ,


3

4

Начал пилить некую систему типов для физических величин, где значение величины имеет семантику умножения безразмерного счётчика на абстрактную единицу измерения, чтобы не надо было каждый раз в публичных API вида SetFrequency(int freq) выяснять что же этот int хранит, а также чтобы не давало складывать метры с литрами и записывать результат в секунды (а также метры с километрами без должной конвертации первого или второго). Существующих велосипедов не нашёл, кроме разве Boost.Units, но это страшный overkill, надо чтобы было маленькое и в одном заголовке.

Базовая идея проста и описана в книжке Страуструпа в главе про <chrono> --

template<typename Rep, typename Period = std::ratio<1>>
class X
{
    Rep mCount;
};
 -- сохраняем значение безразмерного счётчика в фундаментальном типе Rep (int, double, etc), а десятичную приставку в виде рациональной дроби держим только в системе типов на этапе компиляции.

Код тут: https://github.com/Jajauma/SIUnits, содрано с std::chrono::duration, остатки libstdc++ ещё не вычистил полностью, так что на MSVC видимо работать не будет (а может и нигде не будет), главый шаблон SI::Units, для демонстрации там же определены типы Frequency и Length и нескучные пользовательские литералы типа _km, _mm и т.д.

★★★★★

Последнее исправление: d_a (всего исправлений: 2)

Ответ на: комментарий от NeXTSTEP

Идея: производные величины. Например, умножение величины в метрах на такую же даст площадь в квадратных метрах. Ньютоны на метры — джоули и т.п.

Площадь-то добавить нехитро:

struct Meter2;
template <typename Rep, typename Period = std::ratio<1>>
struct Square : public Units<Rep, Period, Meter2>
{
    using Units<Rep, Period, Meter2>::Units;
};
, глобальный оператор и/или функцию нарисовать, которые из аргументов Length будут делать Square. Только это задача приложений по-моему, которым это нужно -- формулы необходимые для работы закодировать. А задача SI::Units -- дать инструмент для определения пользовательских единиц. Frequency и Length наверное тоже стоит спрятать, а то у меня вон уже выше спрашивают где джоули и люмены, хотя я вовсе не хочу переписывать весь учебник по физике.

d_a ★★★★★
() автор топика
Последнее исправление: d_a (всего исправлений: 1)

нескучные пользовательские литералы типа _km, _mm и т.д.

Вот это как раз мой метод, в таких случаях это очень удобное и наглядно.

I-Love-Microsoft ★★★★★
()

Сложно понять, что хочет ТС. Судя по всему он пытается изобрести вещественные числа с намерением не использовать вещественные числа, потому-что последние медленные.

Если нужна универсальность, то почему нельзя все числа хранить в double, предполагая, что эти числа описывают физические величины в системе СИ.

pathfinder ★★★★
()
Ответ на: комментарий от pathfinder

Сложно понять, что хочет ТС. Судя по всему он пытается изобрести вещественные числа с намерением не использовать вещественные числа, потому-что последние медленные.

O_o

Не очень понятно чего непонятно:

чтобы не надо было каждый раз в публичных API вида SetFrequency(int freq) выяснять что же этот int хранит, а также чтобы не давало складывать метры с литрами и записывать результат в секунды (а также метры с километрами без должной конвертации первого или второго).

std::chrono::duration же все видели? Вот хочется также, но для любых единиц, а не только для времени.

BTW, допилил всё мне что сказали.

d_a ★★★★★
() автор топика
Ответ на: комментарий от d_a

Не очень понятно чего непонятно

значение величины имеет семантику умножения безразмерного счётчика на абстрактную единицу измерения

Ты «что» на «что» собрался умножать? Допустим, что безразмерный счетчик это некое целое число, а второй множитель что? Абстрактное понятие?

pathfinder ★★★★
()
Ответ на: комментарий от pathfinder

Омг, это же насколько надо быть тугим, чтобы не осознать что ТС хочет проверку размерностей в компайлтайме.

anonymous
()
Ответ на: комментарий от pathfinder

а второй множитель что? Абстрактное понятие?

Именно так. В алгебраических операцих 1 м участвует так, как если бы это был 1*м. Именно такую семантику реализуют перегруженные операторы для Units<>: сумма и разность дают ту же абстрактную единицу, частное даёт безразмерную величину, а произведение из коробки не определено, так как даёт ещё неизвестную единицу в результате.

d_a ★★★★★
() автор топика
Последнее исправление: d_a (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.