README updated

This commit is contained in:
Mateusz Pusz
2019-04-11 13:54:51 +01:00
parent a49ef2d055
commit d572b50bee

View File

@@ -39,7 +39,7 @@ static_assert(10_km / 5_km == 2);
3. No macros in the user interface 3. No macros in the user interface
4. Easy extensibility 4. Easy extensibility
5. No external dependencies 5. No external dependencies
6. Possibility to be standardized as a part of the C++ Standard Library 6. Possibility to be standardized as a freestanding part of the C++ Standard Library
## Basic Concepts ## Basic Concepts
@@ -111,7 +111,7 @@ However, such an approach have some challenges:
constexpr Velocity auto v1 = 1_m / 1_s; constexpr Velocity auto v1 = 1_m / 1_s;
constexpr Velocity auto v2 = 2 / 2_s * 1_m; constexpr Velocity auto v2 = 2 / 2_s * 1_m;
static_assert(Same<decltype(v1), decltype(v2)>); static_assert(std::Same<decltype(v1), decltype(v2)>);
static_assert(v1 == v2); static_assert(v1 == v2);
``` ```
@@ -215,7 +215,7 @@ expressed in a specific unit of that dimension:
```cpp ```cpp
template<Dimension D, Unit U, Number Rep> template<Dimension D, Unit U, Number Rep>
requires Same<D, typename U::dimension> requires std::Same<D, typename U::dimension>
class quantity; class quantity;
``` ```
@@ -233,7 +233,7 @@ member types and functions as below:
```cpp ```cpp
template<Dimension D, Unit U, Number Rep> template<Dimension D, Unit U, Number Rep>
requires Same<D, typename U::dimension> requires std::Same<D, typename U::dimension>
class quantity { class quantity {
public: public:
using dimension = D; using dimension = D;
@@ -248,13 +248,13 @@ public:
template<Number Rep1, Dimension D, Unit U, Number Rep2> template<Number Rep1, Dimension D, Unit U, Number Rep2>
quantity<dim_invert_t<D>, upcasting_traits_t<unit<dim_invert_t<D>, std::ratio<U::ratio::den, U::ratio::num>>>, std::common_type_t<Rep1, Rep2>> quantity<dim_invert_t<D>, upcasting_traits_t<unit<dim_invert_t<D>, std::ratio<U::ratio::den, U::ratio::num>>>, std::common_type_t<Rep1, Rep2>>
constexpr operator/(const Rep1& v, constexpr operator/(const Rep1& v,
const quantity<D, U, Rep2>& q); const quantity<D, U, Rep2>& q) [[expects: q != quantity<D, U, Rep2>(0)]];
template<Dimension D1, Unit U1, Number Rep1, Dimension D2, Unit U2, Number Rep2> template<Dimension D1, Unit U1, Number Rep1, Dimension D2, Unit U2, Number Rep2>
requires treat_as_floating_point<std::common_type_t<Rep1, Rep2>> || std::ratio_divide<typename U1::ratio, typename U2::ratio>::den == 1 requires treat_as_floating_point<std::common_type_t<Rep1, Rep2>> || std::ratio_divide<typename U1::ratio, typename U2::ratio>::den == 1
quantity<dimension_divide_t<D1, D2>, upcasting_traits_t<unit<dimension_divide_t<D1, D2>, std::ratio_divide<typename U1::ratio, typename U2::ratio>>>, std::common_type_t<Rep1, Rep2>> quantity<dimension_divide_t<D1, D2>, upcasting_traits_t<unit<dimension_divide_t<D1, D2>, std::ratio_divide<typename U1::ratio, typename U2::ratio>>>, std::common_type_t<Rep1, Rep2>>
constexpr operator/(const quantity<D1, U1, Rep1>& lhs, constexpr operator/(const quantity<D1, U1, Rep1>& lhs,
const quantity<D2, U2, Rep2>& rhs); const quantity<D2, U2, Rep2>& rhs) [[expects: rhs != quantity<D, U2, Rep2>(0)]];
}; };
``` ```
@@ -285,14 +285,14 @@ C:\repos\units\example\example.cpp:39:22: error: deduced initializer does not sa
^~~~ ^~~~
In file included from C:\repos\units\example\example.cpp:23: In file included from C:\repos\units\example\example.cpp:23:
C:/repos/units/src/include/units/si/velocity.h:41:16: note: within 'template<class T> concept const bool units::Velocity<T> [with T = units::quantity<units::dimension<units::exp<units::base_dim_time, 1> >, units::unit<units::dimension<units::exp<units::base_dim_time, 1> >, std::ratio<1> >, long long int>]' C:/repos/units/src/include/units/si/velocity.h:41:16: note: within 'template<class T> concept const bool units::Velocity<T> [with T = units::quantity<units::dimension<units::exp<units::base_dim_time, 1> >, units::unit<units::dimension<units::exp<units::base_dim_time, 1> >, std::ratio<1> >, long long int>]'
concept Velocity = Quantity<T> && Same<typename T::dimension, dimension_velocity>; concept Velocity = Quantity<T> && std::Same<typename T::dimension, dimension_velocity>;
^~~~~~~~ ^~~~~~~~
In file included from C:/repos/units/src/include/units/bits/tools.h:25, In file included from C:/repos/units/src/include/units/bits/tools.h:25,
from C:/repos/units/src/include/units/dimension.h:25, from C:/repos/units/src/include/units/dimension.h:25,
from C:/repos/units/src/include/units/si/base_dimensions.h:25, from C:/repos/units/src/include/units/si/base_dimensions.h:25,
from C:/repos/units/src/include/units/si/velocity.h:25, from C:/repos/units/src/include/units/si/velocity.h:25,
from C:\repos\units\example\example.cpp:23: from C:\repos\units\example\example.cpp:23:
C:/repos/units/src/include/units/bits/stdconcepts.h:33:18: note: within 'template<class T, class U> concept const bool mp::std_concepts::Same<T, U> [with T = units::dimension<units::exp<units::base_dim_time, 1> >; U = units::dimension<units::exp<units::base_dim_length, 1>, units::exp<units::base_dim_time, -1> >]' C:/repos/units/src/include/units/bits/stdconcepts.h:33:18: note: within 'template<class T, class U> concept const bool std::Same<T, U> [with T = units::dimension<units::exp<units::base_dim_time, 1> >; U = units::dimension<units::exp<units::base_dim_length, 1>, units::exp<units::base_dim_time, -1> >]'
concept Same = std::is_same_v<T, U>; concept Same = std::is_same_v<T, U>;
^~~~ ^~~~
C:/repos/units/src/include/units/bits/stdconcepts.h:33:18: note: 'std::is_same_v' evaluated to false C:/repos/units/src/include/units/bits/stdconcepts.h:33:18: note: 'std::is_same_v' evaluated to false
@@ -322,14 +322,14 @@ C:\repos\units\example\example.cpp:40:22: error: deduced initializer does not sa
^~~~ ^~~~
In file included from C:\repos\units\example\example.cpp:23: In file included from C:\repos\units\example\example.cpp:23:
C:/repos/units/src/include/units/si/velocity.h:48:16: note: within 'template<class T> concept const bool units::Velocity<T> [with T = units::quantity<units::dimension_time, units::second, long long int>]' C:/repos/units/src/include/units/si/velocity.h:48:16: note: within 'template<class T> concept const bool units::Velocity<T> [with T = units::quantity<units::dimension_time, units::second, long long int>]'
concept Velocity = Quantity<T> && Same<typename T::dimension, dimension_velocity>; concept Velocity = Quantity<T> && std::Same<typename T::dimension, dimension_velocity>;
^~~~~~~~ ^~~~~~~~
In file included from C:/repos/units/src/include/units/bits/tools.h:25, In file included from C:/repos/units/src/include/units/bits/tools.h:25,
from C:/repos/units/src/include/units/dimension.h:25, from C:/repos/units/src/include/units/dimension.h:25,
from C:/repos/units/src/include/units/si/base_dimensions.h:25, from C:/repos/units/src/include/units/si/base_dimensions.h:25,
from C:/repos/units/src/include/units/si/velocity.h:25, from C:/repos/units/src/include/units/si/velocity.h:25,
from C:\repos\units\example\example.cpp:23: from C:\repos\units\example\example.cpp:23:
C:/repos/units/src/include/units/bits/stdconcepts.h:33:18: note: within 'template<class T, class U> concept const bool mp::std_concepts::Same<T, U> [with T = units::dimension_time; U = units::dimension_velocity]' C:/repos/units/src/include/units/bits/stdconcepts.h:33:18: note: within 'template<class T, class U> concept const bool std::Same<T, U> [with T = units::dimension_time; U = units::dimension_velocity]'
concept Same = std::is_same_v<T, U>; concept Same = std::is_same_v<T, U>;
^~~~ ^~~~
C:/repos/units/src/include/units/bits/stdconcepts.h:33:18: note: 'std::is_same_v' evaluated to false C:/repos/units/src/include/units/bits/stdconcepts.h:33:18: note: 'std::is_same_v' evaluated to false
@@ -379,36 +379,50 @@ template<> struct upcasting_traits<upcast_from<kilometer>> : upcast_to<kilometer
``` ```
## Adding new dimensions ## Adding new derived dimensions
In order to extend the library with custom dimensions the user has to: In order to extend the library with custom dimensions the user has to:
1. Create a new dimension type and provide upcasting trait for it: 1. Create a new dimension type with the recipe of how to construct it from base dimensions and provide
upcasting trait for it:
```cpp ```cpp
struct dimension_velocity : make_dimension_t<exp<base_dim_length, 1>, exp<base_dim_time, -1>> {}; struct dimension_velocity : make_dimension_t<exp<base_dim_length, 1>, exp<base_dim_time, -1>> {};
template<> struct upcasting_traits<upcast_from<dimension_velocity>> : upcast_to<dimension_velocity> {}; template<> struct upcasting_traits<upcast_from<dimension_velocity>> : upcast_to<dimension_velocity> {};
``` ```
2. Define the base unit (`std::ratio<1>`) and secondary ones and provide upcasting traits for them via: 2. Provide `quantity` class template partial specialization for new dimension and provide its base type:
```cpp ```cpp
struct meter_per_second : unit<dimension_velocity, std::ratio<1>> {}; template<Unit U = struct meter_per_second, Number Rep = double>
template<> struct upcasting_traits<upcast_from<meter_per_second>> : upcast_to<meter_per_second> {}; using velocity = quantity<dimension_velocity, U, Rep>;
``` ```
3. Define a concept that will match a new dimension: 3. Define a concept that will match a new dimension:
```cpp ```cpp
template<typename T> template<typename T>
concept Velocity = Quantity<T> && Same<typename T::dimension, dimension_velocity>; concept Velocity = Quantity<T> && std::Same<typename T::dimension, dimension_velocity>;
``` ```
4. Provide user-defined literals for the most important units: 4. Define the base and secondary units and provide upcasting traits for them:
```cpp
struct meter_per_second : derived_unit<dimension_velocity, meter, second> {};
template<> struct upcasting_traits<upcast_from<meter_per_second>> : upcast_to<meter_per_second> {};
struct kilometer_per_hour : derived_unit<dimension_velocity, kilometer, hour> {};
template<> struct upcasting_traits<upcast_from<kilometer_per_hour>> : upcast_to<kilometer_per_hour> {};
```
5. Provide user-defined literals for the most important units:
```cpp ```cpp
inline namespace literals { inline namespace literals {
constexpr auto operator""_mps(unsigned long long l) { return velocity<meter_per_second, std::int64_t>(l); } constexpr auto operator""_mps(unsigned long long l) { return velocity<meter_per_second, std::int64_t>(l); }
constexpr auto operator""_mps(long double l) { return velocity<meter_per_second, long double>(l); } constexpr auto operator""_mps(long double l) { return velocity<meter_per_second, long double>(l); }
constexpr auto operator""_kmph(unsigned long long l) { return velocity<kilometer_per_hour, std::int64_t>(l); }
constexpr auto operator""_kmph(long double l) { return velocity<kilometer_per_hour, long double>(l); }
} }
``` ```
@@ -507,7 +521,7 @@ Additionally, it should make the error logs even shorter thus easier to understa
17. Should we leave `quantity` and specific dimensions as 17. Should we leave `quantity` and specific dimensions as
```cpp ```cpp
template<Dimension D, Unit U, Number Rep> template<Dimension D, Unit U, Number Rep>
requires std::experimental::ranges::Same<D, typename U::dimension> requires std::Same<D, typename U::dimension>
class quantity; class quantity;
template<Unit U = meter_per_second, Number Rep = double> template<Unit U = meter_per_second, Number Rep = double>