|
Unit Conversion and Dimensional Analysis Library 3.6.1
A compile-time, header-only C++23 dimensional-analysis library
|
Giving a quantity a type makes the compiler refuse the operations that have no physical meaning. This page catalogs the mistakes the library is built to catch, and shows the verbatim diagnostic each one produces. The diagnostics below are captured directly from the compiler by the error-message test harness (run.py --emit-doc), so what you read here is what the compiler emits, not a paraphrase.
Each example is a case in test/errorMessages/cases/; the harness asserts that it fails to compile and that the diagnostic names the named unit type. The text shown is GCC 13. Clang and MSVC produce equivalent messages (different wording, same named types); the harness verifies all three.
A recurring theme: 3.x names the type — meters<double>, seconds<double>, square_meters<double> — instead of the underlying conversion_factor<...> template. The class-based named units produce that naming; how it is built is covered in the named-type internals.
You cannot add a length to a time. The diagnostic names both operands.
Multiplying two lengths produces an area. Assigning that to a meters is rejected. GCC surfaces the product through an internal alias but names the type right beside it in {aka …}:
The remedy is to name the correct result type — square_meters a = 1.0_m * 1.0_m; — or use auto.
A conversion that would lose information does not happen implicitly. Feet-to-meters is not an integer-exact ratio, so it cannot bind to a meters<int>:
Implicit conversions are allowed only when they are lossless. See the FAQ on integer representations, and use a floating-point representation (meters<double>) or an explicit .to<int>() (which truncates toward zero) when you intend to narrow.
A raw double is not a length; you cannot add one to a meters. (A dimensionless quantity is the one exception — it converts to and from arithmetic types implicitly.)
Trigonometric functions require an angle. Calling sin on a length is rejected. (Note that sqrt of a length is not an error — units supports rational dimensions, so the square root of a length is a well-defined type. It is trigonometry, logarithms, and the like that require a dimensionless or angular argument.)
Two quantities of different dimensions are not ordered, so a relational comparison between a length and a mass does not compile. The failure surfaces in std::common_type (there is no common type for the two), and it names both units:
The template context is longer than the others because the comparison is rejected through std::common_type; the useful part is the substitution line, which names meters_ and kilograms_ as the two types with no common type.
Every diagnostic above corresponds to a defect a bare double would have accepted silently — a unit mismatch, a dimensional error, a lossy conversion, a category confusion. Each is caught at compile time, with a message that names the actual types. For the design reasoning behind the strictness (why conversions are lossless-only, why scalars and dimensioned quantities do not mix), see why units and the FAQ.