diff --git a/include/xo/unit/quantity.hpp b/include/xo/unit/quantity.hpp new file mode 100644 index 00000000..1ab9c137 --- /dev/null +++ b/include/xo/unit/quantity.hpp @@ -0,0 +1,53 @@ +/** @file quantity.hpp + * + * Author: Roland Conybeare + **/ + +#pragma once + +#include "natural_unit.hpp" +#include "scaled_unit.hpp" + +namespace xo { + namespace qty { + /** @class quantity + * @brief represent a scalar quantity with associated units. + * + * Enforce dimensional consistency at compile time. + * sizeof(quantity) == sizeof(Repr). + **/ + template < + typename Repr = double, + typename Int = std::int64_t, + natural_unit NaturalUnit = natural_unit(), + typename Int2x = detail::width2x + > + class quantity { + public: + using repr_type = Repr; + using unit_type = natural_unit; + using ratio_int_type = Int; + using ratio_int2x_type = Int2x; + + public: + constexpr quantity() : scale_{0} {} + explicit constexpr quantity(Repr scale) : scale_{scale} {} + + constexpr const repr_type & scale() const { return scale_; } + constexpr const unit_type & unit() const { return s_unit; } + + constexpr nu_abbrev_type abbrev() const { return s_unit.abbrev(); } + + public: /* need public members so that a quantity instance can be a non-type template parameter (is a structural type) */ + static constexpr natural_unit s_unit = NaturalUnit; + + Repr scale_ = Repr{}; + }; + + namespace qty { + inline constexpr auto grams(double x) { return quantity(x); } + } + } /*namespace qty*/ +} /*namespace xo*/ + +/** end quantity.hpp **/ diff --git a/utest/CMakeLists.txt b/utest/CMakeLists.txt index 33a24f16..852ad319 100644 --- a/utest/CMakeLists.txt +++ b/utest/CMakeLists.txt @@ -4,6 +4,7 @@ set(SELF_EXE utest.unit) set(SELF_SRCS unit_utest_main.cpp #mpl_unit.test.cpp Quantity.test.cpp + quantity.test.cpp bpu.test.cpp basis_unit.test.cpp natural_unit.test.cpp diff --git a/utest/quantity.test.cpp b/utest/quantity.test.cpp new file mode 100644 index 00000000..07bb736c --- /dev/null +++ b/utest/quantity.test.cpp @@ -0,0 +1,30 @@ +/* @file quantity.test.cpp */ + +#include "xo/unit/quantity.hpp" +#include "xo/indentlog/scope.hpp" +#include + +namespace xo { + namespace qty { + TEST_CASE("quantity", "[quantity]") { + constexpr bool c_debug_flag = true; + + // can get bits from /dev/random by uncommenting the 2nd line below + //uint64_t seed = xxx; + //rng::Seed seed; + + //auto rng = xo::rng::xoshiro256ss(seed); + + scope log(XO_DEBUG2(c_debug_flag, "TEST_CASE.quantity")); + //log && log("(A)", xtag("foo", foo)); + + constexpr auto g = qty::grams(1.0); + + static_assert(g.scale() == 1.0); + + log && log(xtag("g.abbrev", g.abbrev())); + } /*TEST_CASE(quantity)*/ + } /*namespace qty*/ +} /*namespace xo*/ + +/* end quantity.test.cpp */