forked from mpusz/mp-units
"Conversions and Casting" chapter done
This commit is contained in:
@@ -89,6 +89,7 @@ add_custom_command(OUTPUT "${SPHINX_INDEX_FILE}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/systems.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/reference/types.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/scenarios.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/scenarios/custom_representation_types.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/scenarios/extensions.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/scenarios/legacy_interfaces.rst"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/scenarios/unknown_units_and_dimensions.rst"
|
||||
|
@@ -3,14 +3,93 @@
|
||||
Conversions and Casting
|
||||
=======================
|
||||
|
||||
Implicit Conversions
|
||||
--------------------
|
||||
Programmers who are not full-time programming language geeks **hate lack of
|
||||
implicit conversions** that they consider reasonable. Violate their expectations
|
||||
for reasons they consider hypothetical problems and you get disuse. In type
|
||||
terms, I usually **translate "reasonable" to "not narrowing" aka "not loosing
|
||||
information."** That can reasonably easily be explained to non-language-experts.
|
||||
|
||||
constructors
|
||||
-- *Bjarne Stroustrup*
|
||||
|
||||
Explicit Casting
|
||||
----------------
|
||||
The library tries to follow the above principle and at the same time is also consistent
|
||||
with conversions of ``std::chrono::duration``.
|
||||
|
||||
quantity_cast
|
||||
|
||||
Example of casting to a dimension's coherent unit.
|
||||
No conversions
|
||||
--------------
|
||||
|
||||
No conversions (either implicit or explicit) are available across quantities of
|
||||
different dimensions::
|
||||
|
||||
si::length<si::metre> d1 = 1q_s; // Compile-time error
|
||||
si::length<si::metre> d2(1q_s); // Compile-time error
|
||||
auto d3 = quantity_cast<si::metre>(1q_s); // Compile-time error
|
||||
|
||||
|
||||
Implicit
|
||||
--------
|
||||
|
||||
Implicit conversions are allowed only across quantities of the same dimension:
|
||||
|
||||
- for integral types with ratios that guarantee no precision loss::
|
||||
|
||||
si::length<si::metre, int> d1 = 1q_km + 1q_m; // OK
|
||||
si::length<si::millimetre, int> d2 = 1q_km + 1q_m; // OK
|
||||
si::length<si::kilometre, int> d3 = 1q_km + 1q_m; // Compile-time error
|
||||
si::length<si::kilometre, int> d4(1q_km + 1q_m); // Compile-time error
|
||||
si::length<si::metre, int> d5 = 1q_m + 1q_ft; // Compile-time error
|
||||
si::length<si::metre, int> d6(1q_m + 1q_ft); // Compile-time error
|
||||
|
||||
- from an integral to a floating-point representation even in case of a truncating
|
||||
ratio::
|
||||
|
||||
si::length<si::kilometre, double> d7 = 1q_km + 1q_m; // OK
|
||||
si::length<si::metre, double> d8 = 1q_m + 1q_ft; // OK
|
||||
|
||||
- when both sides use a floating-point representation::
|
||||
|
||||
si::length<si::metre, int> d9 = 1.23q_m; // Compile-time error
|
||||
si::length<si::metre, double> d10 = 1.23q_m; // OK
|
||||
|
||||
|
||||
Explicit
|
||||
--------
|
||||
|
||||
Explicit conversions are available with a `quantity_cast` function template. They
|
||||
are especially useful to force a truncating conversion across quantities of the same
|
||||
dimension for integral representation types and ratios that may cause precision loss::
|
||||
|
||||
si::length<si::kilometre, int> d1 = quantity_cast<kilometre>(1km + 1m); // OK
|
||||
si::length<si::kilometre, int> d2 = quantity_cast<kilometre>(1s); // Error
|
||||
|
||||
.. seealso::
|
||||
|
||||
Explicit casts are also really useful when working with legacy interfaces. More
|
||||
information on this subject can be found in :ref:`Working with Legacy Interfaces`
|
||||
chapter.
|
||||
|
||||
Quantity Cast Overloads
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
`quantity_cast` comes with several overloads:
|
||||
|
||||
.. code-block::
|
||||
:linenos:
|
||||
|
||||
std::cout << "Distance: " << quantity_cast<si::length<si::metre, int>>(d) << '\n';
|
||||
std::cout << "Distance: " << quantity_cast<si::metre>(d) << '\n';
|
||||
std::cout << "Distance: " << quantity_cast<int>(d) << '\n';
|
||||
|
||||
`quantity_cast` in line #1 takes a specific target `quantity` type to which an explicit
|
||||
cast should be performed. This option will change multiple quantity properties at once
|
||||
(unit, representation, etc). However, it is also possible to force only one property at
|
||||
once and leave the rest intact:
|
||||
|
||||
- line #2 forces only a specific destination unit type,
|
||||
- line #3 sets only a representation type to the type provided by the user.
|
||||
|
||||
.. seealso::
|
||||
|
||||
It is possible to extend above "integral" vs "floating-point" logic for conversions
|
||||
and casting rules to custom representation types. For more information please refer
|
||||
to the :ref:`Customization points` chapter.
|
||||
|
@@ -12,4 +12,5 @@ Scenarios
|
||||
|
||||
scenarios/unknown_units_and_dimensions
|
||||
scenarios/legacy_interfaces
|
||||
scenarios/custom_representation_types
|
||||
scenarios/extensions
|
||||
|
7
docs/scenarios/custom_representation_types.rst
Normal file
7
docs/scenarios/custom_representation_types.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
.. namespace:: units
|
||||
|
||||
Custom Representation Type
|
||||
==========================
|
||||
|
||||
Customization points
|
||||
--------------------
|
Reference in New Issue
Block a user