cpp-ru / ideas

Идеи по улучшению языка C++ для обсуждения
https://cpp-ru.github.io/proposals
Creative Commons Zero v1.0 Universal
89 stars 0 forks source link

compile-time memory::unit #300

Closed apolukhin closed 3 years ago

apolukhin commented 3 years ago

Перенос предложения: голоса +4, -3 Автор идеи: neondev9

По мотивам std::chrono::duration и по мотивам календаря (С++20), шаблонный тип memory::unit, представляющий собой единицу измерения количества информации, предоставляющий удобные литералы и преобразования в другие размерности, а также арифметику в удобочитаемом виде. Представленный пример работы типа основан на рабочем концепте (С++14). Изменения в ядре никакие не требуются. Имена типов и литералов можно поменять. В арифметике общий тип вычисляется по принципу наименьшей размерности: Кбайт + байт -> байт; Мбайт + Кбайт -> Кбайт.

include "memory_unit.h"

constexpr void Foo()
{
    using namespace memory::literals;

    constexpr memory::bits      a1{1};
    constexpr memory::bytes     a2{1};
    constexpr memory::kilobytes a3{1};
    constexpr memory::megabytes a4{1};
    constexpr memory::gigabytes a5{1};
    constexpr memory::terabytes a6{1};

    constexpr memory::kilobits  a7{1}; // kilobits!
    constexpr memory::megabits  a8{1};
    constexpr memory::gigabits  a9{1};

    constexpr memory::nibbles   b1{1}; // 4 bits
    constexpr memory::words     b2{1}; // platform_type
    // literals
    constexpr memory::bits      literal_1 = 1bit;
    constexpr memory::bytes     literal_2 = 1byte;
    constexpr memory::kilobytes literal_3 = 1kb;
    constexpr memory::megabytes literal_4 = 1mb;
    constexpr memory::gigabytes literal_5 = 1gb;
    constexpr memory::terabytes literal_6 = 1tb;

    constexpr memory::kilobits  literal_7 = 1kbit; 
    constexpr memory::megabits  literal_8 = 1mbit;
    constexpr memory::gigabits  literal_9 = 1gbit;
    // floating-point literals + conversion
    constexpr memory::bytes     e1 = 2.5mb; // 2621440 bytes
    constexpr memory::kilobytes e2 = 2.5mb; // 2560 kilobytes
    // conversion
    constexpr memory::bits      d1 = 1byte; // d3.count() returned 8
    constexpr memory::bytes     d2 = 1kb;   // ok: kilobyte > byte
    constexpr memory::bytes     d3 = 100mb; // ok: megabyte > byte
    constexpr memory::megabytes d4 = 2gb;   // ok: gigabyte > megabyte

    constexpr memory::kilobytes error = 512byte; // error C2440: cannot convert from "memory::bytes" to "memory::kilobytes"
    // but...
    constexpr memory::kilobytes not_error1 = memory::unit_cast<memory::kilobytes>(1024byte); // 1 kilobytes
    constexpr memory::kilobytes not_error2 = memory::floor<memory::kilobytes>(2561byte);     // 2 kilobytes
    constexpr memory::kilobytes not_error3 = memory::ceil <memory::kilobytes>(2561byte);     // 3 kilobytes
    constexpr memory::kilobytes not_error4 = memory::round<memory::kilobytes>(2561byte);     // 3 kilobytes

    constexpr auto floating_point_type = 1.25kb; // typeid: memory::unit<long_double, memory::internal_ratio::kilobytes>
    // arithmetic
    constexpr auto f1 = 3kb + 5kb;  // memory::killobytes{8}
    constexpr auto f2 = 3kb + 5mb;  // 3 kilobytes + 5 megabytes = memory::kilobytes{5123}

    constexpr auto f3 = f2 + 5byte; // 5123 kilobytes + 5 bytes = memory::bytes{5245957}
    constexpr auto f4 = 1gb + 512mb - 100kb; // 1 gigabyte + 512 megabyte - 100 kilobytes = memory::kilobytes{1572764}
    // mixed arithmetic: double + long long int + double
    constexpr auto f5 = 1.25kb + 1mb + 0.07mb; // 1096.93 kilobytes

    // comparison
    constexpr bool g1{ 1kb == 1024byte }; // true
    constexpr bool g2{ 512mb != 0.5gb };  // false
    constexpr bool g3{ 1mb > 1kb };       // true
    constexpr bool g4{ 1tb < 1gb };       // false

}
apolukhin commented 3 years ago

yndx-antoshkka, 3 мая 2018, 14:44 Идея хорошая, но стоит ещё сделать и другие типы данных (физические типы данных, например скорость, ускорение, масса и т.д.)

Artalus, 3 мая 2018, 17:08 В качестве отправной точки можно также взять вот такое чудо.

neondev9, 3 мая 2018, 17:16 Artalus, отличная библиотека. Используется та же концепция, но объём впечатляет)

Сегодня еще искал в boost подобные штуки, нашёл boost::units, суть практически та же, но подход другой и внешний вид не впечатляет.

Andrey Davydov, 4 мая 2018, 20:48 Обновлено 3 мая 2018, 17:19

Это ж можно будет писать

std::byte buffer[4mb / 1byte];

вообще красота!

А 1byte / 1bit предлагаете сделать платформозависимой константой?

И еще, если сама идея такой библиотеки продвинется до обсуждения в комитете, то по поводу именования суффиксов будут очень жаркие дебаты.

A, 6 июля 2018, 14:52 Есть красивая реализация https://github.com/nholthaus/units

apolukhin commented 3 years ago

Mateusz Pusz сейчас работает над этой проблемой. Попрбуйте его библиотеку, дайте feedback если что-то не так https://github.com/mpusz/units

apolukhin commented 3 years ago

Закрываю в пользу #356 , там более говорящий заголовок