From 96dcea751dec0700307f523ef13ac75b7d33e618 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Mon, 5 Feb 2024 19:11:14 +0100 Subject: [PATCH 01/13] feat: improve types readability by eliminating extraneous `()` for a value of a type for prefixes --- .../systems/iec80000/binary_prefixes.h | 32 +++---- .../include/mp-units/systems/si/prefixes.h | 96 +++++++++---------- test/static/unit_test.cpp | 10 +- 3 files changed, 69 insertions(+), 69 deletions(-) diff --git a/src/systems/include/mp-units/systems/iec80000/binary_prefixes.h b/src/systems/include/mp-units/systems/iec80000/binary_prefixes.h index ca3db21e..112e71a8 100644 --- a/src/systems/include/mp-units/systems/iec80000/binary_prefixes.h +++ b/src/systems/include/mp-units/systems/iec80000/binary_prefixes.h @@ -27,23 +27,23 @@ namespace mp_units::iec80000 { // clang-format off -template struct kibi_ : prefixed_unit<"Ki", mag_power<2, 10>, U> {}; -template struct mebi_ : prefixed_unit<"Mi", mag_power<2, 20>, U> {}; -template struct gibi_ : prefixed_unit<"Gi", mag_power<2, 30>, U> {}; -template struct tebi_ : prefixed_unit<"Ti", mag_power<2, 40>, U> {}; -template struct pebi_ : prefixed_unit<"Pi", mag_power<2, 50>, U> {}; -template struct exbi_ : prefixed_unit<"Ei", mag_power<2, 60>, U> {}; -template struct zebi_ : prefixed_unit<"Zi", mag_power<2, 70>, U> {}; -template struct yobi_ : prefixed_unit<"Yi", mag_power<2, 80>, U> {}; +template struct kibi_ : prefixed_unit<"Ki", mag_power<2, 10>, U{}> {}; +template struct mebi_ : prefixed_unit<"Mi", mag_power<2, 20>, U{}> {}; +template struct gibi_ : prefixed_unit<"Gi", mag_power<2, 30>, U{}> {}; +template struct tebi_ : prefixed_unit<"Ti", mag_power<2, 40>, U{}> {}; +template struct pebi_ : prefixed_unit<"Pi", mag_power<2, 50>, U{}> {}; +template struct exbi_ : prefixed_unit<"Ei", mag_power<2, 60>, U{}> {}; +template struct zebi_ : prefixed_unit<"Zi", mag_power<2, 70>, U{}> {}; +template struct yobi_ : prefixed_unit<"Yi", mag_power<2, 80>, U{}> {}; -template inline constexpr kibi_ kibi; -template inline constexpr mebi_ mebi; -template inline constexpr gibi_ gibi; -template inline constexpr tebi_ tebi; -template inline constexpr pebi_ pebi; -template inline constexpr exbi_ exbi; -template inline constexpr zebi_ zebi; -template inline constexpr yobi_ yobi; +template inline constexpr kibi_> kibi; +template inline constexpr mebi_> mebi; +template inline constexpr gibi_> gibi; +template inline constexpr tebi_> tebi; +template inline constexpr pebi_> pebi; +template inline constexpr exbi_> exbi; +template inline constexpr zebi_> zebi; +template inline constexpr yobi_> yobi; // clang-format on } // namespace mp_units::iec80000 diff --git a/src/systems/include/mp-units/systems/si/prefixes.h b/src/systems/include/mp-units/systems/si/prefixes.h index f8c9431c..09582df0 100644 --- a/src/systems/include/mp-units/systems/si/prefixes.h +++ b/src/systems/include/mp-units/systems/si/prefixes.h @@ -27,55 +27,55 @@ namespace mp_units::si { // clang-format off -template struct quecto_ : prefixed_unit<"q", mag_power<10, -30>, U> {}; -template struct ronto_ : prefixed_unit<"r", mag_power<10, -27>, U> {}; -template struct yocto_ : prefixed_unit<"y", mag_power<10, -24>, U> {}; -template struct zepto_ : prefixed_unit<"z", mag_power<10, -21>, U> {}; -template struct atto_ : prefixed_unit<"a", mag_power<10, -18>, U> {}; -template struct femto_ : prefixed_unit<"f", mag_power<10, -15>, U> {}; -template struct pico_ : prefixed_unit<"p", mag_power<10, -12>, U> {}; -template struct nano_ : prefixed_unit<"n", mag_power<10, -9>, U> {}; -template struct micro_ : prefixed_unit, U> {}; -template struct milli_ : prefixed_unit<"m", mag_power<10, -3>, U> {}; -template struct centi_ : prefixed_unit<"c", mag_power<10, -2>, U> {}; -template struct deci_ : prefixed_unit<"d", mag_power<10, -1>, U> {}; -template struct deca_ : prefixed_unit<"da", mag_power<10, 1>, U> {}; -template struct hecto_ : prefixed_unit<"h", mag_power<10, 2>, U> {}; -template struct kilo_ : prefixed_unit<"k", mag_power<10, 3>, U> {}; -template struct mega_ : prefixed_unit<"M", mag_power<10, 6>, U> {}; -template struct giga_ : prefixed_unit<"G", mag_power<10, 9>, U> {}; -template struct tera_ : prefixed_unit<"T", mag_power<10, 12>, U> {}; -template struct peta_ : prefixed_unit<"P", mag_power<10, 15>, U> {}; -template struct exa_ : prefixed_unit<"E", mag_power<10, 18>, U> {}; -template struct zetta_ : prefixed_unit<"Z", mag_power<10, 21>, U> {}; -template struct yotta_ : prefixed_unit<"Y", mag_power<10, 24>, U> {}; -template struct ronna_ : prefixed_unit<"R", mag_power<10, 27>, U> {}; -template struct quetta_ : prefixed_unit<"Q", mag_power<10, 30>, U> {}; +template struct quecto_ : prefixed_unit<"q", mag_power<10, -30>, U{}> {}; +template struct ronto_ : prefixed_unit<"r", mag_power<10, -27>, U{}> {}; +template struct yocto_ : prefixed_unit<"y", mag_power<10, -24>, U{}> {}; +template struct zepto_ : prefixed_unit<"z", mag_power<10, -21>, U{}> {}; +template struct atto_ : prefixed_unit<"a", mag_power<10, -18>, U{}> {}; +template struct femto_ : prefixed_unit<"f", mag_power<10, -15>, U{}> {}; +template struct pico_ : prefixed_unit<"p", mag_power<10, -12>, U{}> {}; +template struct nano_ : prefixed_unit<"n", mag_power<10, -9>, U{}> {}; +template struct micro_ : prefixed_unit, U{}> {}; +template struct milli_ : prefixed_unit<"m", mag_power<10, -3>, U{}> {}; +template struct centi_ : prefixed_unit<"c", mag_power<10, -2>, U{}> {}; +template struct deci_ : prefixed_unit<"d", mag_power<10, -1>, U{}> {}; +template struct deca_ : prefixed_unit<"da", mag_power<10, 1>, U{}> {}; +template struct hecto_ : prefixed_unit<"h", mag_power<10, 2>, U{}> {}; +template struct kilo_ : prefixed_unit<"k", mag_power<10, 3>, U{}> {}; +template struct mega_ : prefixed_unit<"M", mag_power<10, 6>, U{}> {}; +template struct giga_ : prefixed_unit<"G", mag_power<10, 9>, U{}> {}; +template struct tera_ : prefixed_unit<"T", mag_power<10, 12>, U{}> {}; +template struct peta_ : prefixed_unit<"P", mag_power<10, 15>, U{}> {}; +template struct exa_ : prefixed_unit<"E", mag_power<10, 18>, U{}> {}; +template struct zetta_ : prefixed_unit<"Z", mag_power<10, 21>, U{}> {}; +template struct yotta_ : prefixed_unit<"Y", mag_power<10, 24>, U{}> {}; +template struct ronna_ : prefixed_unit<"R", mag_power<10, 27>, U{}> {}; +template struct quetta_ : prefixed_unit<"Q", mag_power<10, 30>, U{}> {}; -template inline constexpr quecto_ quecto; -template inline constexpr ronto_ ronto; -template inline constexpr yocto_ yocto; -template inline constexpr zepto_ zepto; -template inline constexpr atto_ atto; -template inline constexpr femto_ femto; -template inline constexpr pico_ pico; -template inline constexpr nano_ nano; -template inline constexpr micro_ micro; -template inline constexpr milli_ milli; -template inline constexpr centi_ centi; -template inline constexpr deci_ deci; -template inline constexpr deca_ deca; -template inline constexpr hecto_ hecto; -template inline constexpr kilo_ kilo; -template inline constexpr mega_ mega; -template inline constexpr giga_ giga; -template inline constexpr tera_ tera; -template inline constexpr peta_ peta; -template inline constexpr exa_ exa; -template inline constexpr zetta_ zetta; -template inline constexpr yotta_ yotta; -template inline constexpr ronna_ ronna; -template inline constexpr quetta_ quetta; +template inline constexpr quecto_> quecto; +template inline constexpr ronto_> ronto; +template inline constexpr yocto_> yocto; +template inline constexpr zepto_> zepto; +template inline constexpr atto_> atto; +template inline constexpr femto_> femto; +template inline constexpr pico_> pico; +template inline constexpr nano_> nano; +template inline constexpr micro_> micro; +template inline constexpr milli_> milli; +template inline constexpr centi_> centi; +template inline constexpr deci_> deci; +template inline constexpr deca_> deca; +template inline constexpr hecto_> hecto; +template inline constexpr kilo_> kilo; +template inline constexpr mega_> mega; +template inline constexpr giga_> giga; +template inline constexpr tera_> tera; +template inline constexpr peta_> peta; +template inline constexpr exa_> exa; +template inline constexpr zetta_> zetta; +template inline constexpr yotta_> yotta; +template inline constexpr ronna_> ronna; +template inline constexpr quetta_> quetta; // clang-format on } // namespace mp_units::si diff --git a/test/static/unit_test.cpp b/test/static/unit_test.cpp index d187467a..6b3ab4d1 100644 --- a/test/static/unit_test.cpp +++ b/test/static/unit_test.cpp @@ -212,8 +212,8 @@ static_assert(convertible(kilojoule, joule)); static_assert(kilojoule != joule); static_assert(kilojoule.symbol == "kJ"); -static_assert(is_of_type, si::kilo_>); -static_assert(is_of_type, si::kilo_>); +static_assert(is_of_type, si::kilo_>); +static_assert(is_of_type, si::kilo_>); // TODO Should the below be a scaled version of metre^2? static_assert(is_of_type>); // !!! @@ -264,7 +264,7 @@ static_assert(is_of_type); static_assert(get_canonical_unit(km_2).mag == mag<2000>); constexpr auto kJ_42 = mag<42> * si::kilo; -static_assert(is_of_type, si::kilo_>>); +static_assert(is_of_type, si::kilo_>>); static_assert( is_of_type, per>>>); static_assert(get_canonical_unit(kJ_42).mag == mag<42'000'000>); @@ -467,7 +467,7 @@ static_assert(!convertible(metre, metre* metre)); // one static_assert(is_of_type); -static_assert(is_of_type / metre, derived_unit, per>>); +static_assert(is_of_type / metre, derived_unit, per>>); static_assert(metre / metre == one); static_assert(hertz * second == one); static_assert(one * one == one); @@ -509,7 +509,7 @@ static_assert(is_of_type(metre / (second * second)), derived_unit>>); static_assert(is_of_type(kilometre), derived_unit>>); -static_assert(is_of_type(si::kilo), derived_unit, 2>>>); +static_assert(is_of_type(si::kilo), derived_unit, 2>>>); static_assert(is_of_type(hour), derived_unit>>); static_assert( is_of_type(mag<3600>* second), scaled_unit * mag<3600>, derived_unit>>>); From 25a4c7c1287698f868e8e8ec46fb31b8482c73a7 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Mon, 5 Feb 2024 19:32:38 +0100 Subject: [PATCH 02/13] fix: quantity_test compilation fixed --- test/static/quantity_test.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/static/quantity_test.cpp b/test/static/quantity_test.cpp index 7992f493..69386243 100644 --- a/test/static/quantity_test.cpp +++ b/test/static/quantity_test.cpp @@ -520,7 +520,8 @@ static_assert(is_of_type<1 * percent * (1 * m), quantity>{}, int>>); static_assert(is_of_type<1 * m / (1 * m), quantity>); -static_assert(is_of_type<1 * km / (1 * m), quantity, per>{}, int>>); +static_assert( + is_of_type<1 * km / (1 * m), quantity, per>{}, int>>); static_assert(is_of_type<1 * m / 1, quantity>); static_assert(is_of_type<1 * m / (1 * one), quantity>); @@ -568,7 +569,7 @@ static_assert(is_of_type<1 * percent * (1. * m), quantity>{}, double>>); static_assert(is_of_type<1. * m / (1 * m), quantity>); static_assert( - is_of_type<1. * km / (1 * m), quantity, per>{}, double>>); + is_of_type<1. * km / (1 * m), quantity, per>{}, double>>); static_assert(is_of_type<1. * m / 1, quantity>); static_assert(is_of_type<1 * m / (1. * one), quantity>); @@ -612,11 +613,12 @@ static_assert(is_of_type<1 * m * (1 * min), quantity{}, int>>); static_assert(is_of_type<1 / (1 * min), quantity>{}, int>>); static_assert(is_of_type<1 / (1 * Hz), quantity>{}, int>>); -static_assert(is_of_type<1 / (1 * km), quantity>>{}, int>>); +static_assert(is_of_type<1 / (1 * km), quantity>>{}, int>>); static_assert(is_of_type<1 / min, quantity>{}, int>>); static_assert(is_of_type<1 / Hz, quantity>{}, int>>); -static_assert(is_of_type<1 / km, quantity>>{}, int>>); -static_assert(is_of_type<1 * km / (1 * m), quantity, per>{}, int>>); +static_assert(is_of_type<1 / km, quantity>>{}, int>>); +static_assert( + is_of_type<1 * km / (1 * m), quantity, per>{}, int>>); static_assert(is_of_type<1 * m / (1 * s), quantity>{}, int>>); static_assert(is_of_type<1 * m / (1 * min), quantity>{}, int>>); static_assert(is_of_type<1 * min / (1 * m), quantity>{}, int>>); From 8b5d2ead52dc6483794d88f374d014a3dc77cea2 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Mon, 5 Feb 2024 19:45:08 +0100 Subject: [PATCH 03/13] fix: si_test compilation fixed --- test/static/si_test.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/static/si_test.cpp b/test/static/si_test.cpp index 8ce65935..0599469b 100644 --- a/test/static/si_test.cpp +++ b/test/static/si_test.cpp @@ -61,8 +61,9 @@ static_assert(1 * Rm == 1'000'000'000'000'000'000 * Gm); static_assert(1 * Qm == 1'000'000'000'000'000'000 * Tm); // check for invalid prefixes -template typename prefix, auto V1> -concept can_not_be_prefixed = Unit> && !requires { typename prefix; }; +template typename prefix, auto V1> +concept can_not_be_prefixed = + Unit> && !requires { typename prefix>; }; static_assert(can_not_be_prefixed); static_assert(can_not_be_prefixed); From 862e39ec9724c66bdead0d8a0368174f44211288 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Sat, 10 Feb 2024 12:19:44 +0100 Subject: [PATCH 04/13] refactor: :boom: Conan config options renamed to `user.mp-units.*` --- .github/workflows/ci-conan.yml | 4 +-- .github/workflows/ci-test-package-cmake.yml | 2 +- .github/workflows/codeql.yml | 2 +- .gitpod.yml | 32 +++++++++---------- .gitpod/conan/global.conf | 1 + CONTRIBUTING.md | 10 +++++- conanfile.py | 8 ++--- .../getting_started/installation_and_usage.md | 20 ++++++------ 8 files changed, 44 insertions(+), 35 deletions(-) diff --git a/.github/workflows/ci-conan.yml b/.github/workflows/ci-conan.yml index 52b4955c..6a154b8b 100644 --- a/.github/workflows/ci-conan.yml +++ b/.github/workflows/ci-conan.yml @@ -47,7 +47,7 @@ jobs: # name: "MSVC 14.2", # os: windows-2019, # compiler: { type: VISUAL, version: 16, cc: "", cxx: "" }, - # conan-config: "-c user.build:skip_la=True", + # conan-config: "-c user.mp-units.build:skip_la=True", # } # - { # name: "MSVC 14.3", @@ -212,7 +212,7 @@ jobs: run: | conan create . --user mpusz --channel ${CHANNEL} --lockfile-out=package.lock \ -b mp-units/* -b missing -c tools.cmake.cmaketoolchain:generator="Ninja Multi-Config" \ - -c user.build:all=True -o cxx_modules=${{ matrix.config.cxx_modules }} -o use_fmtlib=${{ env.use_fmtlib }} ${{ matrix.config.conan-config }} + -c user.mp-units.build:all=True -o cxx_modules=${{ matrix.config.cxx_modules }} -o use_fmtlib=${{ env.use_fmtlib }} ${{ matrix.config.conan-config }} - name: Obtain package reference id: get-package-ref shell: bash diff --git a/.github/workflows/ci-test-package-cmake.yml b/.github/workflows/ci-test-package-cmake.yml index a24bbefb..82000cb9 100644 --- a/.github/workflows/ci-test-package-cmake.yml +++ b/.github/workflows/ci-test-package-cmake.yml @@ -205,7 +205,7 @@ jobs: - name: Install Conan dependencies shell: bash run: | - conan install . -b missing -c tools.cmake.cmaketoolchain:generator="Ninja Multi-Config" -c user.build:all=False \ + conan install . -b missing -c tools.cmake.cmaketoolchain:generator="Ninja Multi-Config" -c user.mp-units.build:all=False \ -o cxx_modules=${{ matrix.config.cxx_modules }} -o use_fmtlib=${{ env.use_fmtlib }} mv CMakeUserPresets.json src - name: Configure mp-units CMake diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d8464ae8..6f29802c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -105,7 +105,7 @@ jobs: conan profile detect --force conan remote add artifactory https://mpusz.jfrog.io/artifactory/api/conan/conan-oss mkdir _lgtm_build_dir && cd _lgtm_build_dir - conan build .. -s compiler.cppstd=20 -c user.build:all=True -o use_fmtlib=True -b missing + conan build .. -s compiler.cppstd=20 -c user.mp-units.build:all=True -o use_fmtlib=True -b missing - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 diff --git a/.gitpod.yml b/.gitpod.yml index 82da5910..155b6c8a 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -71,17 +71,17 @@ tasks: gp sync-await python-init conan profile detect conan config install $PWD/.gitpod/conan - conan install . -pr gcc12 -c user.build:all=True -o use_fmtlib=True -b missing - conan install . -pr gcc12 -c user.build:all=True -o use_fmtlib=True -b missing -s build_type=Debug + conan install . -pr gcc12 -o use_fmtlib=True -b missing + conan install . -pr gcc12 -o use_fmtlib=True -b missing -s build_type=Debug gp sync-done conan-gcc12-20 - conan install . -pr gcc13 -c user.build:all=True -b missing - conan install . -pr gcc13 -c user.build:all=True -b missing -s build_type=Debug + conan install . -pr gcc13 -b missing + conan install . -pr gcc13 -b missing -s build_type=Debug gp sync-done conan-gcc13-20 - conan install . -pr clang16 -c user.build:all=True -o use_fmtlib=True -b missing - conan install . -pr clang16 -c user.build:all=True -o use_fmtlib=True -b missing -s build_type=Debug + conan install . -pr clang16 -o use_fmtlib=True -b missing + conan install . -pr clang16 -o use_fmtlib=True -b missing -s build_type=Debug gp sync-done conan-clang16-20 - conan install . -pr clang17 -c user.build:all=True -o cxx_modules=True -b missing - conan install . -pr clang17 -c user.build:all=True -o cxx_modules=True -b missing -s build_type=Debug + conan install . -pr clang17 -o cxx_modules=True -b missing + conan install . -pr clang17 -o cxx_modules=True -b missing -s build_type=Debug gp sync-done conan-clang17-20 conan remote login -p $ARTIFACTORY_TOKEN conan-gitpod-mp-units $ARTIFACTORY_USER conan upload "*" -r conan-gitpod-mp-units -c @@ -89,29 +89,29 @@ tasks: init: | gp sync-await conan-gcc12-20 source ${PYTHON_VENV}/bin/activate - conan build . -pr gcc12 -c user.build:all=True -o use_fmtlib=True - conan build . -pr gcc12 -c user.build:all=True -o use_fmtlib=True -s build_type=Debug + conan build . -pr gcc12 -o use_fmtlib=True + conan build . -pr gcc12 -o use_fmtlib=True -s build_type=Debug echo "🛠️ gcc-12 pre-build done for C++20, header files, and libfmt! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️" - name: gcc-13-20 init: | gp sync-await conan-gcc13-20 source ${PYTHON_VENV}/bin/activate - conan build . -pr gcc13 -c user.build:all=True - conan build . -pr gcc13 -c user.build:all=True -s build_type=Debug + conan build . -pr gcc13 + conan build . -pr gcc13 -s build_type=Debug echo "🛠️ gcc-13 pre-build done for C++20 and header files! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️" - name: clang-16-20 init: | gp sync-await conan-clang16-20 source ${PYTHON_VENV}/bin/activate - conan build . -pr clang16 -c user.build:all=True -o use_fmtlib=True - conan build . -pr clang16 -c user.build:all=True -o use_fmtlib=True -s build_type=Debug + conan build . -pr clang16 -o use_fmtlib=True + conan build . -pr clang16 -o use_fmtlib=True -s build_type=Debug echo "🛠️ clang-16 pre-build done for C++20, header files, and libfmt! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️" - name: clang-17-20 init: | gp sync-await conan-clang17-20 source ${PYTHON_VENV}/bin/activate - conan build . -pr clang17 -c user.build:all=True -o cxx_modules=True - conan build . -pr clang17 -c user.build:all=True -o cxx_modules=True -s build_type=Debug + conan build . -pr clang17 -o cxx_modules=True + conan build . -pr clang17 -o cxx_modules=True -s build_type=Debug echo "🛠️ clang-17 pre-build done for C++20! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️" - name: documentation init: | diff --git a/.gitpod/conan/global.conf b/.gitpod/conan/global.conf index 6840876c..29ce8bd5 100644 --- a/.gitpod/conan/global.conf +++ b/.gitpod/conan/global.conf @@ -1,2 +1,3 @@ tools.cmake.cmaketoolchain:generator=Ninja Multi-Config tools.cmake.cmake_layout:build_folder_vars=["settings.compiler", "settings.compiler.version", "settings.compiler.cppstd"] +user.mp-units.build:all=True diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 32f4730b..ae27af60 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -56,13 +56,21 @@ After the script is done please make sure to stage all those changes to git comm The simplest way to verify if all targets build correctly and all unit tests pass is to run: ```bash -conan build . -pr -s compiler.cppstd=23 -o cxx_modules=True -c user.build:all=True -b missing +conan build . -pr -s compiler.cppstd=23 -o cxx_modules=True -c user.mp-units.build:all=True -b missing ``` as described in the [Installation and Usage](https://mpusz.github.io/mp-units/latest/getting_started/installation_and_usage/#contributing-or-just-building-all-the-tests-and-examples) chapter of our documentation. +_Hint:_ To ensure that that we always build all the targets and to save some typing of the Conan commands, +it is a good practice to set the following in the `~/.conan2/global.conf`: + +```text +user.mp-units.build:all=True +``` + + ### Backward Compatibility Before submission, please remember to check if the code compiles fine on the supported compilers. diff --git a/conanfile.py b/conanfile.py index 2825223b..aab04f5c 100644 --- a/conanfile.py +++ b/conanfile.py @@ -83,7 +83,7 @@ class MPUnitsConan(ConanFile): return { "gcc": "12", "clang": "16", - "apple-clang": "15" + "apple-clang": "15", # , "msvc": "192" } @@ -91,18 +91,18 @@ class MPUnitsConan(ConanFile): def _std_format_minimum_compilers_version(self): return { "gcc": "13", - "clang": "17" + "clang": "17", # , "apple-clang": "15" # , "msvc": "192" } @property def _build_all(self): - return bool(self.conf.get("user.build:all", default=False)) + return bool(self.conf.get("user.mp-units.build:all", default=False)) @property def _skip_la(self): - return bool(self.conf.get("user.build:skip_la", default=False)) + return bool(self.conf.get("user.mp-units.build:skip_la", default=False)) def set_version(self): content = load(self, os.path.join(self.recipe_folder, "src/CMakeLists.txt")) diff --git a/docs/getting_started/installation_and_usage.md b/docs/getting_started/installation_and_usage.md index 0ebf89c6..1dca2e2a 100644 --- a/docs/getting_started/installation_and_usage.md +++ b/docs/getting_started/installation_and_usage.md @@ -194,9 +194,9 @@ tools.build:compiler_executables={"c": "gcc-12", "cpp": "g++-12"} ### Conan configuration properties -[`user.build:all`](#user-build-all){ #user-build-all } +[`user.mp-units.build:all`](#user.mp-units.build-all){ #user.mp-units.build-all } -: [:octicons-tag-24: 0.8.0][build all support] · :octicons-milestone-24: `True`/`False` (Default: `False`) +: [:octicons-tag-24: 2.2.0][build all support] · :octicons-milestone-24: `True`/`False` (Default: `False`) Enables compilation of all the source code, including tests and examples. To support this, it requires some additional Conan build dependencies described in [Repository Structure and Dependencies](#repository-structure-and-dependencies). @@ -204,19 +204,19 @@ tools.build:compiler_executables={"c": "gcc-12", "cpp": "g++-12"} [`tools.build:skip_test`](https://docs.conan.io/2/reference/commands/config.html?highlight=tools.build:skip_test#conan-config-list) configuration property is set to `True`). - [build all support]: https://github.com/mpusz/mp-units/releases/tag/v0.8.0 + [build all support]: https://github.com/mpusz/mp-units/releases/tag/v2.2.0 -[`user.build:skip_la`](#user-skip-la){ #user-skip-la } +[`user.mp-units.build:skip_la`](#user-skip-la){ #user-skip-la } -: [:octicons-tag-24: 0.8.0][skip la support] · :octicons-milestone-24: `True`/`False` (Default: `False`) +: [:octicons-tag-24: 2.2.0][skip la support] · :octicons-milestone-24: `True`/`False` (Default: `False`) - If `user.build:all` is enabled, among others, Conan installs the external + If `user.mp-units.build:all` is enabled, among others, Conan installs the external [wg21-linear_algebra](https://conan.io/center/recipes/wg21-linear_algebra) dependency and enables the compilation of linear algebra-based tests and usage examples. Such behavior can be disabled with this option. - [skip la support]: https://github.com/mpusz/mp-units/releases/tag/v0.8.0 + [skip la support]: https://github.com/mpusz/mp-units/releases/tag/v2.2.0 ### CMake options @@ -453,11 +453,11 @@ In case you would like to build all the **mp-units** source code (with unit test you should: 1. Use the _CMakeLists.txt_ from the top-level directory. -2. Run Conan with [`user.build:all`](#user-build-all) = `True`. +2. Run Conan with [`user.mp-units.build:all`](#user.mp-units.build-all) = `True`. ```shell git clone https://github.com/mpusz/mp-units.git && cd units -conan build . -pr -s compiler.cppstd=23 -o cxx_modules=True -c user.build:all=True -b missing +conan build . -pr -s compiler.cppstd=23 -o cxx_modules=True -c user.mp-units.build:all=True -b missing ``` The above will download and install all of the dependencies needed for the development of the library, @@ -504,7 +504,7 @@ After that, you can either: To test CMake installation and Conan packaging or create a Conan package run: ```shell -conan create . --user --channel -pr -s compiler.cppstd=20 -o cxx_modules=True -c user.build:all=True -b missing +conan create . --user --channel -pr -s compiler.cppstd=20 -o cxx_modules=True -c user.mp-units.build:all=True -b missing ``` The above will create a Conan package and run tests provided in _./test_package_ directory. From c313c2c083a8699351b3d97d7d0523d53dcd87f4 Mon Sep 17 00:00:00 2001 From: Nick Thompson Date: Sat, 10 Feb 2024 08:33:52 -0800 Subject: [PATCH 05/13] Ensure mp-units are compatible with std::atomic --- test/runtime/CMakeLists.txt | 2 +- test/runtime/atomic_test.cpp | 40 ++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 test/runtime/atomic_test.cpp diff --git a/test/runtime/CMakeLists.txt b/test/runtime/CMakeLists.txt index b22c7022..897957a9 100644 --- a/test/runtime/CMakeLists.txt +++ b/test/runtime/CMakeLists.txt @@ -24,7 +24,7 @@ cmake_minimum_required(VERSION 3.5) find_package(Catch2 3 REQUIRED) -add_executable(unit_tests_runtime distribution_test.cpp fmt_test.cpp math_test.cpp) +add_executable(unit_tests_runtime distribution_test.cpp fmt_test.cpp math_test.cpp atomic_test.cpp) if(${projectPrefix}BUILD_CXX_MODULES) target_compile_definitions(unit_tests_runtime PUBLIC ${projectPrefix}MODULES) endif() diff --git a/test/runtime/atomic_test.cpp b/test/runtime/atomic_test.cpp new file mode 100644 index 00000000..800626dc --- /dev/null +++ b/test/runtime/atomic_test.cpp @@ -0,0 +1,40 @@ +// The MIT License (MIT) +// +// Copyright (c) 2024 Nick Thompson +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace mp_units; +using namespace mp_units::si::unit_symbols; + +TEST_CASE("std::atomic works with dimensioned types", "[atomic][assignment]") +{ + std::atomic a = 3.0 * isq::area[m2]; + std::atomic b = 3.0 * isq::area[m2]; + REQUIRE(a == b); +} From 947baa6d676fd8a34dcfdebade61df58d6198853 Mon Sep 17 00:00:00 2001 From: Nick Date: Sat, 10 Feb 2024 09:35:04 -0800 Subject: [PATCH 06/13] Update test/runtime/atomic_test.cpp Co-authored-by: Mateusz Pusz --- test/runtime/atomic_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/runtime/atomic_test.cpp b/test/runtime/atomic_test.cpp index 800626dc..2269f2ca 100644 --- a/test/runtime/atomic_test.cpp +++ b/test/runtime/atomic_test.cpp @@ -34,7 +34,7 @@ using namespace mp_units::si::unit_symbols; TEST_CASE("std::atomic works with dimensioned types", "[atomic][assignment]") { - std::atomic a = 3.0 * isq::area[m2]; - std::atomic b = 3.0 * isq::area[m2]; + std::atomic> a = 3.0 * isq::area[m2]; + std::atomic> b = 3.0 * isq::area[m2]; REQUIRE(a == b); } From 34eac6a61e4dcfb903cc11e2df083a0176a8c1a1 Mon Sep 17 00:00:00 2001 From: Nick Date: Sat, 10 Feb 2024 09:52:26 -0800 Subject: [PATCH 07/13] Update test/runtime/atomic_test.cpp Co-authored-by: Mateusz Pusz --- test/runtime/atomic_test.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/test/runtime/atomic_test.cpp b/test/runtime/atomic_test.cpp index 2269f2ca..ba382edf 100644 --- a/test/runtime/atomic_test.cpp +++ b/test/runtime/atomic_test.cpp @@ -21,9 +21,6 @@ // SOFTWARE. #include -#include -#include -#include #include #include #include @@ -34,7 +31,7 @@ using namespace mp_units::si::unit_symbols; TEST_CASE("std::atomic works with dimensioned types", "[atomic][assignment]") { - std::atomic> a = 3.0 * isq::area[m2]; - std::atomic> b = 3.0 * isq::area[m2]; - REQUIRE(a == b); + std::atomic> a1 = 3.0 * isq::area[m2]; + std::atomic> a2 = 3.0 * isq::area[m2]; + REQUIRE(a1.load() == a2.load()); } From f16ac802b3b39b765cf1169505a2713eae0755ea Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Tue, 13 Feb 2024 16:26:38 +0100 Subject: [PATCH 08/13] fix: a value set for `__cpp_explicit_this_parameter` --- src/core/include/mp-units/bits/external/hacks.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/include/mp-units/bits/external/hacks.h b/src/core/include/mp-units/bits/external/hacks.h index cbe2b05b..a24a884a 100644 --- a/src/core/include/mp-units/bits/external/hacks.h +++ b/src/core/include/mp-units/bits/external/hacks.h @@ -83,7 +83,7 @@ // TODO revise the below when clang-18 is released #if MP_UNITS_COMP_CLANG >= 18 && !defined __cpp_explicit_this_parameter -#define __cpp_explicit_this_parameter +#define __cpp_explicit_this_parameter 202110L #endif From 202c1d10da689d5cc62f5f61080d579fa92f38d0 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Tue, 13 Feb 2024 20:23:03 +0100 Subject: [PATCH 09/13] refactor: `get_kind()` now returns `kind_of` --- .../mp-units/bits/quantity_spec_concepts.h | 4 +- src/core/include/mp-units/quantity_spec.h | 86 +++++++++++-------- 2 files changed, 51 insertions(+), 39 deletions(-) diff --git a/src/core/include/mp-units/bits/quantity_spec_concepts.h b/src/core/include/mp-units/bits/quantity_spec_concepts.h index d685c923..9ee2b690 100644 --- a/src/core/include/mp-units/bits/quantity_spec_concepts.h +++ b/src/core/include/mp-units/bits/quantity_spec_concepts.h @@ -130,7 +130,7 @@ concept QuantitySpec = detail::NamedQuantitySpec || detail::IntermediateDerivedQuantitySpec || detail::QuantityKindSpec; template -[[nodiscard]] consteval QuantitySpec auto get_kind(Q q); +[[nodiscard]] consteval detail::QuantityKindSpec auto get_kind(Q q); namespace detail { @@ -138,7 +138,7 @@ template concept NestedQuantityKindSpecOf = QuantitySpec> && QuantitySpec> && get_kind(From) != get_kind(To) && - std::derived_from, std::remove_cvref_t>; + std::derived_from, std::remove_cvref_t>; } diff --git a/src/core/include/mp-units/quantity_spec.h b/src/core/include/mp-units/quantity_spec.h index ae958d04..d0524a77 100644 --- a/src/core/include/mp-units/quantity_spec.h +++ b/src/core/include/mp-units/quantity_spec.h @@ -444,11 +444,15 @@ namespace detail { template concept QuantitySpecWithNoSpecifiers = detail::NamedQuantitySpec || detail::IntermediateDerivedQuantitySpec; +template +[[nodiscard]] consteval QuantitySpec auto get_kind_tree_root(Q q); + } // namespace detail #ifdef __cpp_explicit_this_parameter template - requires(detail::QuantitySpecWithNoSpecifiers>) && (get_kind(Q) == Q) + requires(detail::QuantitySpecWithNoSpecifiers>) && + (detail::detail::get_kind_tree_root(Q) == Q) struct kind_of_ : std::remove_const_t { static constexpr auto _quantity_spec_ = Q; }; @@ -456,10 +460,11 @@ struct kind_of_ : std::remove_const_t { #if MP_UNITS_COMP_CLANG template - requires detail::QuantitySpecWithNoSpecifiers> && (get_kind(Q) == Q) + requires detail::QuantitySpecWithNoSpecifiers> && + (detail::get_kind_tree_root(Q) == Q) #else template - requires(get_kind(Q) == Q) + requires(detail::get_kind_tree_root(Q) == Q) #endif struct kind_of_ : quantity_spec, Q> { static constexpr auto _quantity_spec_ = Q; @@ -467,7 +472,7 @@ struct kind_of_ : quantity_spec, Q> { #endif template - requires(get_kind(Q) == Q) + requires(detail::get_kind_tree_root(Q) == Q) inline constexpr kind_of_ kind_of; namespace detail { @@ -484,6 +489,15 @@ template return q; } +template +[[nodiscard]] consteval auto remove_kind(Q q) +{ + if constexpr (detail::QuantityKindSpec) + return Q::_quantity_spec_; + else + return q; +} + } // namespace detail // Operators @@ -493,7 +507,7 @@ template { return detail::clone_kind_of( detail::expr_multiply( - remove_kind(lhs), remove_kind(rhs))); + detail::remove_kind(lhs), detail::remove_kind(rhs))); } template @@ -501,7 +515,7 @@ template { return detail::clone_kind_of( detail::expr_divide( - remove_kind(lhs), remove_kind(rhs))); + detail::remove_kind(lhs), detail::remove_kind(rhs))); } template @@ -538,13 +552,13 @@ template else if constexpr (detail::IntermediateDerivedQuantitySpec) return detail::clone_kind_of( detail::expr_pow( - remove_kind(q))); + detail::remove_kind(q))); else if constexpr (Den == 1) return detail::clone_kind_of( - derived_quantity_spec, Num>>{}); + derived_quantity_spec, Num>>{}); else return detail::clone_kind_of( - derived_quantity_spec, Num, Den>>{}); + derived_quantity_spec, Num, Den>>{}); } @@ -1315,8 +1329,8 @@ template else if constexpr (From{} == To{}) return yes; else if constexpr (QuantityKindSpec || QuantityKindSpec) { - constexpr auto from_kind = get_kind(From{}); - constexpr auto to_kind = get_kind(To{}); + constexpr auto from_kind = get_kind_tree_root(From{}); + constexpr auto to_kind = get_kind_tree_root(To{}); constexpr auto exploded_kind_result = [](specs_convertible_result res) { using enum specs_convertible_result; return res == no ? no : yes; @@ -1327,11 +1341,11 @@ template return convertible_impl(from_kind, to_kind); else if constexpr (get_complexity(from_kind) > get_complexity(to_kind)) return exploded_kind_result( - convertible_impl(get_kind(explode(from_kind).quantity), to_kind)); + convertible_impl(get_kind_tree_root(explode(from_kind).quantity), to_kind)); else return exploded_kind_result( - convertible_impl(from_kind, get_kind(explode(to_kind).quantity))); - } else if constexpr (NestedQuantityKindSpecOf && get_kind(To{}) == To{}) + convertible_impl(from_kind, get_kind_tree_root(explode(to_kind).quantity))); + } else if constexpr (NestedQuantityKindSpecOf && get_kind_tree_root(To{}) == To{}) return yes; else if constexpr (NamedQuantitySpec && NamedQuantitySpec) { if constexpr (have_common_base(From{}, To{})) { @@ -1401,8 +1415,8 @@ template namespace detail { template - requires requires(Q q) { get_kind(q); } -using to_kind = std::remove_const_t; + requires requires(Q q) { get_kind_tree_root(q); } +using to_kind = std::remove_const_t; #ifdef __cpp_explicit_this_parameter template @@ -1415,19 +1429,8 @@ template return contains(); } -} // namespace detail - template -[[nodiscard]] consteval auto remove_kind(Q q) -{ - if constexpr (detail::QuantityKindSpec) - return Q::_quantity_spec_; - else - return q; -} - -template -[[nodiscard]] consteval QuantitySpec auto get_kind(Q q) +[[nodiscard]] consteval QuantitySpec auto get_kind_tree_root(Q q) { auto defined_as_kind = [](QQ qq) { if constexpr (requires { detail::defined_as_kind(qq); }) @@ -1441,7 +1444,7 @@ template } else if constexpr (defined_as_kind(Q{})) { return q; } else if constexpr (requires { Q::_parent_; }) { - return get_kind(Q::_parent_); + return get_kind_tree_root(Q::_parent_); } else if constexpr (detail::IntermediateDerivedQuantitySpec) { return detail::expr_map(q); @@ -1451,20 +1454,29 @@ template } } +} // namespace detail + +template +[[nodiscard]] consteval detail::QuantityKindSpec auto get_kind(Q q) +{ + return kind_of; +} + [[nodiscard]] consteval QuantitySpec auto common_quantity_spec(QuantitySpec auto q) { return q; } template [[nodiscard]] consteval QuantitySpec auto common_quantity_spec(Q1 q1, Q2 q2) - requires(implicitly_convertible(get_kind(q1), get_kind(q2)) || implicitly_convertible(get_kind(q2), get_kind(q1))) + requires(implicitly_convertible(get_kind_tree_root(q1), get_kind_tree_root(q2)) || + implicitly_convertible(get_kind_tree_root(q2), get_kind_tree_root(q1))) { - using QQ1 = std::remove_const_t; - using QQ2 = std::remove_const_t; + using QQ1 = std::remove_const_t; + using QQ2 = std::remove_const_t; if constexpr (is_same_v) return q1; else if constexpr (detail::NestedQuantityKindSpecOf) - return remove_kind(q1); + return detail::remove_kind(q1); else if constexpr (detail::NestedQuantityKindSpecOf) - return remove_kind(q2); + return detail::remove_kind(q2); else if constexpr ((detail::QuantityKindSpec && !detail::QuantityKindSpec) || (detail::IntermediateDerivedQuantitySpec && detail::NamedQuantitySpec && implicitly_convertible(Q1{}, Q2{}))) @@ -1479,10 +1491,10 @@ template return q2; else if constexpr (implicitly_convertible(Q2{}, Q1{})) return q1; - else if constexpr (implicitly_convertible(get_kind(Q1{}), get_kind(Q2{}))) - return get_kind(q2); + else if constexpr (implicitly_convertible(get_kind_tree_root(Q1{}), get_kind_tree_root(Q2{}))) + return get_kind_tree_root(q2); else - return get_kind(q1); + return get_kind_tree_root(q1); } [[nodiscard]] consteval QuantitySpec auto common_quantity_spec(QuantitySpec auto q1, QuantitySpec auto q2, From f1353a716669c1fad935e565a4c7bd879914885a Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Tue, 13 Feb 2024 20:25:28 +0100 Subject: [PATCH 10/13] docs: `get_kind()` note added to "Systems of Quantities" chapter --- docs/users_guide/framework_basics/systems_of_quantities.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/users_guide/framework_basics/systems_of_quantities.md b/docs/users_guide/framework_basics/systems_of_quantities.md index 080972bb..c87e493f 100644 --- a/docs/users_guide/framework_basics/systems_of_quantities.md +++ b/docs/users_guide/framework_basics/systems_of_quantities.md @@ -392,4 +392,9 @@ static_assert(same_type / isq::time, isq::length / isq::tim Only a root quantity from the hierarchy tree or the one marked with `is_kind` specifier in the `quantity_spec` definition can be put as a template parameter to the `kind_of` - specifier. For example, `kind_of` will fail to compile. + specifier. For example, `kind_of` will fail to compile. However, we can call + `get_kind(q)` to obtain a kind of any quantity: + + ```cpp + static_assert(get_kind(isq::width) == kind_of); + ``` From 2e609d9d6d85b8e8b188422fe9d5d030dbcacff0 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Tue, 13 Feb 2024 21:14:00 +0100 Subject: [PATCH 11/13] fix: add missing unit test changes --- test/static/quantity_spec_test.cpp | 40 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/test/static/quantity_spec_test.cpp b/test/static/quantity_spec_test.cpp index d9713686..b845e4c8 100644 --- a/test/static/quantity_spec_test.cpp +++ b/test/static/quantity_spec_test.cpp @@ -396,25 +396,25 @@ static_assert(acceleration * (time * time) != position_vector); static_assert(acceleration / speed != frequency); // get_kind -static_assert(get_kind(length) == length); -static_assert(get_kind(distance) == length); -static_assert(get_kind(time) == time); -static_assert(get_kind(period_duration) == time); -static_assert(get_kind(length / time) == length / time); -static_assert(get_kind(speed) == speed); -static_assert(get_kind(height / time) == length / time); -static_assert(get_kind(inverse(time)) == inverse(time)); -static_assert(get_kind(inverse(period_duration)) == inverse(time)); -static_assert(get_kind(frequency) == frequency); -static_assert(get_kind(mass * frequency) == mass * frequency); -static_assert(get_kind(moment_of_force) == moment_of_force); -static_assert(get_kind(energy) == energy); -static_assert(get_kind(potential_energy) == energy); -static_assert(get_kind(kinetic_energy) == energy); -static_assert(get_kind(pow<1, 2>(area)) == pow<1, 2>(area)); -static_assert(get_kind(angular_measure) == angular_measure); -static_assert(get_kind(phase_angle) == angular_measure); -static_assert(get_kind(rotational_displacement) == angular_measure); +static_assert(get_kind(length) == kind_of); +static_assert(get_kind(distance) == kind_of); +static_assert(get_kind(time) == kind_of