A type-safe, header-only C++23 library for temperature handling, modeled after std::chrono.
Features
- Type-safe temperatures with distinct types for Celsius, Kelvin, and Fahrenheit
- Configurable precision (degree, decidegree, millidegree)
- Automatic conversions between scales and precisions
- Lossless implicit conversions (lossy conversions require explicit casts)
- Temperature deltas distinct from absolute temperatures
- User-defined literals for concise notation
std::formatsupport (when available)- Fully constexpr - all operations can be evaluated at compile time
Requirements
- C++23 compiler (GCC 13+, Clang 17+, MSVC 19.36+)
- MSVC users: The following compiler flags are required:
/std:c++latest- Enable C++23 features/Zc:__cplusplus- Set__cplusplusmacro correctly/utf-8- Treat source files as UTF-8 (for degree symbols)
Installation
CMake FetchContent
include(FetchContent) FetchContent_Declare( thermo GIT_REPOSITORY https://github.com/cleishm/thermo-cpp.git GIT_TAG v1.0.0 ) FetchContent_MakeAvailable(thermo) target_link_libraries(your_target PRIVATE thermo::thermo)
vcpkg
vcpkg install cleishm-thermo-cpp
find_package(thermo CONFIG REQUIRED) target_link_libraries(your_target PRIVATE thermo::thermo)
Manual
Copy the include/thermo/ directory to your project.
Usage
#include <thermo/thermo> // or <thermo/thermo.hpp> using namespace thermo; using namespace thermo_literals; // Absolute temperatures celsius room_temp{20}; kelvin absolute = room_temp; // implicit conversion to higher precision fahrenheit f = fahrenheit(room_temp); // explicit cross-scale conversion // Using literals auto boiling = 100_c; auto freezing = 32_f; auto absolute_zero = 0_k; // Precision control millicelsius precise{25500}; // 25.5°C celsius coarse = celsius(precise); // explicit lossy conversion (truncates to 25°C) millicelsius back = coarse; // implicit lossless conversion (25000 m°C) // Temperature deltas (differences) auto delta = 5_Δc; // 5 degree change auto new_temp = room_temp + delta; // 25°C // Computing differences delta_celsius diff = difference(boiling, room_temp); // 80°C difference // Comparisons work across precisions if (millicelsius{20000} == celsius{20}) { // true - same temperature, different precision } // String conversion std::string s = to_string(room_temp); // "20°C"
Temperature Types
Absolute Temperatures
| Type | Scale | Precision |
|---|---|---|
celsius |
Celsius | 1°C |
decicelsius |
Celsius | 0.1°C |
millicelsius |
Celsius | 0.001°C |
kelvin |
Kelvin | 1 K |
decikelvin |
Kelvin | 0.1 K |
millikelvin |
Kelvin | 0.001 K |
fahrenheit |
Fahrenheit | 1°F |
decifahrenheit |
Fahrenheit | 0.1°F |
millifahrenheit |
Fahrenheit | 0.001°F |
Temperature Deltas
| Type | Precision |
|---|---|
delta_celsius / delta_kelvin |
1° |
delta_decicelsius / delta_decikelvin |
0.1° |
delta_millicelsius / delta_millikelvin |
0.001° |
delta_fahrenheit |
1°F (= 5/9°C) |
delta_decifahrenheit |
0.1°F |
delta_millifahrenheit |
0.001°F |
Literals
using namespace thermo_literals; // Absolute temperatures 20_c // celsius(20) 200_dc // decicelsius(200) = 20.0°C 20000_mc // millicelsius(20000) = 20.000°C 293_k // kelvin(293) 68_f // fahrenheit(68) // Temperature deltas 5_Δc // delta_celsius(5) 5000_Δmc // delta_millicelsius(5000) 9_Δf // delta_fahrenheit(9) = delta_celsius(5)
Conversion Rules
Conversions follow the same philosophy as std::chrono:
- Implicit conversions are allowed when lossless (e.g.,
celsius→millicelsius) - Explicit conversions are required when lossy (e.g.,
millicelsius→celsius) - Cross-scale conversions consider both precision and scale offset
// Implicit (lossless) millicelsius mc = celsius{20}; // OK: 20°C → 20000 m°C millikelvin mk = millicelsius{0}; // OK: 0 m°C → 273150 mK // Explicit required (lossy) celsius c = celsius(millicelsius{1500}); // 1500 m°C → 1°C (truncates) kelvin k = kelvin(celsius{0}); // 0°C → 273 K (truncates 273.15) // Use temperature_cast for explicit conversions auto k2 = temperature_cast<kelvin>(celsius{100});
Building Tests
cmake -B build -DTHERMO_BUILD_TESTS=ON cmake --build build ctest --test-dir build
Building with MSVC
When using MSVC, you must pass the required compiler flags:
cmake -B build -DTHERMO_BUILD_TESTS=ON -DCMAKE_CXX_FLAGS="/std:c++latest /Zc:__cplusplus /utf-8 /EHsc"
cmake --build build --config Release
ctest --test-dir build -C ReleaseLicense
MIT License - see LICENSE for details.