| 
									
										
										
										
											2023-06-21 10:55:18 +02:00
										 |  |  | # Value Conversions
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Value-preserving conversions
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```cpp | 
					
						
							|  |  |  | auto q1 = 5 * km; | 
					
						
							| 
									
										
										
										
											2023-08-23 16:46:15 +02:00
										 |  |  | std::cout << q1.in(m) << '\n'; | 
					
						
							| 
									
										
										
										
											2023-06-21 10:55:18 +02:00
										 |  |  | quantity<si::metre, int> q2 = q1; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The second line above converts the current quantity to the one expressed in metres and prints its | 
					
						
							|  |  |  | contents. The third line converts the quantity expressed in kilometres into the one measured | 
					
						
							|  |  |  | in metres. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-30 11:33:30 +02:00
										 |  |  | !!! important | 
					
						
							| 
									
										
										
										
											2023-06-21 10:55:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     It is always assumed that one can convert a quantity into another one with a unit of a higher | 
					
						
							|  |  |  |     resolution. There is no protection against overflow of the representation type. In case the target | 
					
						
							|  |  |  |     quantity ends up with a value bigger than the representation type can handle, you will be facing | 
					
						
							|  |  |  |     Undefined Behavior. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In case a user would like to perform an opposite transformation: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```cpp | 
					
						
							|  |  |  | auto q1 = 5 * m; | 
					
						
							| 
									
										
										
										
											2023-08-23 16:46:15 +02:00
										 |  |  | std::cout << q1.in(km) << '\n'; | 
					
						
							| 
									
										
										
										
											2023-06-21 10:55:18 +02:00
										 |  |  | quantity<si::kilo<si::metre>, int> q2 = q1; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Both conversions will fail to compile. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | There are two ways to make the above work. The first solution is to use a floating-point | 
					
						
							|  |  |  | representation type: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```cpp | 
					
						
							|  |  |  | auto q1 = 5. * m; | 
					
						
							| 
									
										
										
										
											2023-08-23 16:46:15 +02:00
										 |  |  | std::cout << q1.in(km) << '\n'; | 
					
						
							| 
									
										
										
										
											2023-06-21 10:55:18 +02:00
										 |  |  | quantity<si::kilo<si::metre>> q2 = q1; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-13 09:00:21 +02:00
										 |  |  | or | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```cpp | 
					
						
							|  |  |  | auto q1 = 5 * m; | 
					
						
							|  |  |  | std::cout << value_cast<double>(q1).in(km) << '\n'; | 
					
						
							|  |  |  | quantity<si::kilo<si::metre>> q2 = q1;  // double by default | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-31 18:57:39 +02:00
										 |  |  | !!! important | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     The **mp-units** library follows [`std::chrono::duration`](https://en.cppreference.com/w/cpp/chrono/duration) | 
					
						
							|  |  |  |     logic and treats floating-point types as value-preserving. | 
					
						
							| 
									
										
										
										
											2023-06-21 10:55:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Value-truncating conversions
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The second solution is to force a truncating conversion: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```cpp | 
					
						
							|  |  |  | auto q1 = 5 * m; | 
					
						
							|  |  |  | std::cout << value_cast<km>(q1) << '\n'; | 
					
						
							| 
									
										
										
										
											2023-09-13 10:44:50 +02:00
										 |  |  | quantity<si::kilo<si::metre>, int> q2 = q1.force_in(km); | 
					
						
							| 
									
										
										
										
											2023-06-21 10:55:18 +02:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This explicit cast makes it clear that something unsafe is going on. It is easy to spot in code | 
					
						
							|  |  |  | reviews or while chasing a bug in the source code. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-13 10:44:50 +02:00
										 |  |  | !!! note | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     `q.force_in(U)` is just a shortcut to run `value_cast<U>(q)`. There is no difference in behavior | 
					
						
							|  |  |  |     between those two interfaces. `q.force_in(U)` was added for consistency with `q.in(U)` and | 
					
						
							|  |  |  |     `q.force_numerical_value_in(U)`. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 10:55:18 +02:00
										 |  |  | Another place where this cast is useful is when a user wants to convert a quantity with | 
					
						
							|  |  |  | a floating-point representation to the one using an integral one. Again this is a truncating | 
					
						
							|  |  |  | conversion, so an explicit cast is needed: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```cpp | 
					
						
							|  |  |  | quantity<si::metre, int> q3 = value_cast<int>(3.14 * m); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | !!! info | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     It is often fine to use an integral as a representation type, but in general, floating-point | 
					
						
							|  |  |  |     types provide better precision and are privileged in the library as they are considered | 
					
						
							|  |  |  |     to be value-preserving. |