diff --git a/.cmake-format.yaml b/.cmake-format.yaml index 45da65a4..2956b76e 100644 --- a/.cmake-format.yaml +++ b/.cmake-format.yaml @@ -4,19 +4,25 @@ parse: pargs: nargs: 1 flags: - - ALL + - ALL kwargs: BREATHE_PROJECT: 1 CODE_SOURCE_DIR: 1 INSTALL_DIR: 1 CODE_DEPENDS: 1 DOCS_DEPENDS: 1 + add_units_module: + pargs: + nargs: 1 + kwargs: + DEPENDENCIES: + + HEADERS: + enable_iwyu: pargs: flags: - - NO_FORWARD_DECLARATIONS - - QUOTED_INCLUDES_FIRST - - NO_COMMENTS + - NO_FORWARD_DECLARATIONS + - QUOTED_INCLUDES_FIRST + - NO_COMMENTS kwargs: MAPPING_FILE: 1 MAX_LINE_LENGTH: 1 diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..6deafc26 --- /dev/null +++ b/.flake8 @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 120 diff --git a/.github/workflows/ci-conan.yml b/.github/workflows/ci-conan.yml index 9a4f3ecc..0c1ad283 100644 --- a/.github/workflows/ci-conan.yml +++ b/.github/workflows/ci-conan.yml @@ -25,10 +25,10 @@ name: Conan CI on: push: paths-ignore: - - 'docs/**' + - "docs/**" pull_request: paths-ignore: - - 'docs/**' + - "docs/**" jobs: build: @@ -38,51 +38,108 @@ jobs: fail-fast: false matrix: config: - - { - name: "Windows MSVC 14.2", - os: windows-2019, - compiler: { type: VISUAL, version: 16, std: 20, cc: "cl", cxx: "cl" } - } - - { - name: "Windows MSVC 14.3", - os: windows-2022, - compiler: { type: MSVC, version: 193, std: 23, cc: "cl", cxx: "cl" } - } - - { - name: "Ubuntu GCC-10", - os: ubuntu-20.04, - compiler: { type: GCC, version: 10, cc: "gcc-10", cxx: "g++-10", std: 20 }, - lib: "libstdc++11" - } - - { - name: "Ubuntu GCC-11", - os: ubuntu-20.04, - compiler: { type: GCC, version: 11, cc: "gcc-11", cxx: "g++-11", std: 20 }, - lib: "libstdc++11" - } - - { - name: "Ubuntu Clang-12 + libstdc++11", - os: ubuntu-20.04, - compiler: { type: CLANG, version: 12, cc: "clang-12", cxx: "clang++-12", std: 20 }, - lib: "libstdc++11" - } - - { - name: "Ubuntu Clang-12 + libc++", - os: ubuntu-20.04, - compiler: { type: CLANG, version: 12, cc: "clang-12", cxx: "clang++-12", std: 20 }, - lib: "libc++" - } - - { - name: "Ubuntu Clang-13 + libc++", - os: ubuntu-20.04, - compiler: { type: CLANG, version: 13, cc: "clang-13", cxx: "clang++-13", std: 20 }, - lib: "libc++" - } - - { - name: "MacOS Apple Clang 13", - os: macos-11, - compiler: { type: APPLE_CLANG, version: "13.0", cc: "clang", cxx: "clang++", std: 20 } - } + - { + name: "Windows MSVC 14.2", + os: windows-2019, + compiler: + { type: VISUAL, version: 16, std: 20, cc: "cl", cxx: "cl" }, + } + - { + name: "Windows MSVC 14.3", + os: windows-2022, + compiler: + { type: MSVC, version: 193, std: 23, cc: "cl", cxx: "cl" }, + } + - { + name: "Ubuntu GCC-10", + os: ubuntu-20.04, + compiler: + { + type: GCC, + version: 10, + cc: "gcc-10", + cxx: "g++-10", + std: 20, + }, + lib: "libstdc++11", + } + - { + name: "Ubuntu GCC-11", + os: ubuntu-20.04, + compiler: + { + type: GCC, + version: 11, + cc: "gcc-11", + cxx: "g++-11", + std: 20, + }, + lib: "libstdc++11", + } + - { + name: "Ubuntu Clang-12 + libstdc++11", + os: ubuntu-20.04, + compiler: + { + type: CLANG, + version: 12, + cc: "clang-12", + cxx: "clang++-12", + std: 20, + }, + lib: "libstdc++11", + } + - { + name: "Ubuntu Clang-12 + libc++", + os: ubuntu-20.04, + compiler: + { + type: CLANG, + version: 12, + cc: "clang-12", + cxx: "clang++-12", + std: 20, + }, + lib: "libc++", + } + - { + name: "Ubuntu Clang-13 + libc++", + os: ubuntu-20.04, + compiler: + { + type: CLANG, + version: 13, + cc: "clang-13", + cxx: "clang++-13", + std: 20, + }, + lib: "libc++", + } + - { + name: "Ubuntu Clang-14 + libc++", + os: ubuntu-20.04, + compiler: + { + type: CLANG, + version: 14, + cc: "clang-14", + cxx: "clang++-14", + std: 20, + }, + lib: "libc++", + } + - { + name: "MacOS Apple Clang 13", + os: macos-11, + compiler: + { + type: APPLE_CLANG, + version: "13.0", + cc: "clang", + cxx: "clang++", + std: 20, + }, + } # In case a Conan docker image will be needed to provide a specific configuration we can use a Docker image as follows # - { # name: "Ubuntu GCC 10.2.0", @@ -90,8 +147,8 @@ jobs: # compiler: { type: GCC, version: 10, cc: "gcc-10", cxx: "g++-10" }, # docker_image: conanio/gcc10 # } - build_type: [ "Release", "Debug" ] - downcast_mode: [ "on", "auto" ] + build_type: ["Release", "Debug"] + downcast_mode: ["on", "auto"] steps: - uses: actions/checkout@v2 - uses: hendrikmuhs/ccache-action@v1 @@ -141,7 +198,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: '3.8' + python-version: "3.8" - name: Install Conan Package Tools run: | pip install -U conan_package_tools diff --git a/.github/workflows/ci-test-package-cmake.yml b/.github/workflows/ci-test-package-cmake.yml index 568083a7..2c6440ac 100644 --- a/.github/workflows/ci-test-package-cmake.yml +++ b/.github/workflows/ci-test-package-cmake.yml @@ -25,14 +25,14 @@ name: CMake Test Package CI on: push: paths-ignore: - - 'docs/**' - - 'example/**' - - 'test/**' + - "docs/**" + - "example/**" + - "test/**" pull_request: paths-ignore: - - 'docs/**' - - 'example/**' - - 'test/**' + - "docs/**" + - "example/**" + - "test/**" jobs: test_package: @@ -42,46 +42,62 @@ jobs: fail-fast: false matrix: config: - - { - name: "Windows MSVC 2019", - os: windows-latest, - compiler: { type: VISUAL, version: 16, cc: "", cxx: "" } - } - - { - name: "Ubuntu GCC 10.3.0", - os: ubuntu-20.04, - compiler: { type: GCC, version: 10, cc: "gcc-10", cxx: "g++-10" }, - lib: "libstdc++11" - } - - { - name: "Ubuntu GCC 11.1.0", - os: ubuntu-20.04, - compiler: { type: GCC, version: 11, cc: "gcc-11", cxx: "g++-11" }, - lib: "libstdc++11" - } - - { - name: "Ubuntu Clang 12.0.0 + libstdc++11", - os: ubuntu-20.04, - compiler: { type: CLANG, version: 12, cc: "clang-12", cxx: "clang++-12" }, - lib: "libstdc++11" - } - - { - name: "Ubuntu Clang 12.0.0 + libc++", - os: ubuntu-20.04, - compiler: { type: CLANG, version: 12, cc: "clang-12", cxx: "clang++-12" }, - lib: "libc++" - } - - { - name: "Ubuntu Clang 13.0.0 + libc++", - os: ubuntu-20.04, - compiler: { type: CLANG, version: 13, cc: "clang-13", cxx: "clang++-13" }, - lib: "libc++" - } - - { - name: "MacOS Apple Clang 13", - os: macos-11, - compiler: { type: APPLE_CLANG, version: "13.0", cc: "clang", cxx: "clang++" } - } + - { + name: "Windows MSVC 2019", + os: windows-latest, + compiler: { type: VISUAL, version: 16, cc: "", cxx: "" }, + } + - { + name: "Ubuntu GCC 10.3.0", + os: ubuntu-20.04, + compiler: { type: GCC, version: 10, cc: "gcc-10", cxx: "g++-10" }, + lib: "libstdc++11", + } + - { + name: "Ubuntu GCC 11.1.0", + os: ubuntu-20.04, + compiler: { type: GCC, version: 11, cc: "gcc-11", cxx: "g++-11" }, + lib: "libstdc++11", + } + - { + name: "Ubuntu Clang 12.0.0 + libstdc++11", + os: ubuntu-20.04, + compiler: + { type: CLANG, version: 12, cc: "clang-12", cxx: "clang++-12" }, + lib: "libstdc++11", + } + - { + name: "Ubuntu Clang 12.0.0 + libc++", + os: ubuntu-20.04, + compiler: + { type: CLANG, version: 12, cc: "clang-12", cxx: "clang++-12" }, + lib: "libc++", + } + - { + name: "Ubuntu Clang 13.0.0 + libc++", + os: ubuntu-20.04, + compiler: + { type: CLANG, version: 13, cc: "clang-13", cxx: "clang++-13" }, + lib: "libc++", + } + - { + name: "Ubuntu Clang 14.0.0 + libc++", + os: ubuntu-20.04, + compiler: + { type: CLANG, version: 14, cc: "clang-14", cxx: "clang++-14" }, + lib: "libc++", + } + - { + name: "MacOS Apple Clang 13", + os: macos-11, + compiler: + { + type: APPLE_CLANG, + version: "13.0", + cc: "clang", + cxx: "clang++", + }, + } # In case a Conan docker image will be needed to provide a specific configuration we can use a Docker image as follows # - { # name: "Ubuntu GCC 10.2.0", @@ -89,7 +105,7 @@ jobs: # compiler: { type: GCC, version: 10, cc: "gcc-10", cxx: "g++-10" }, # docker_image: conanio/gcc10 # } - build_type: [ "Release", "Debug" ] + build_type: ["Release", "Debug"] env: CC: ${{ matrix.config.compiler.cc }} @@ -151,7 +167,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: '3.8' + python-version: "3.8" - name: Install Conan shell: bash run: | @@ -185,13 +201,13 @@ jobs: working-directory: build/${{ matrix.build_type }} run: | call conanvcvars.bat - cmake ../../src -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake + cmake ../../src -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} - name: Configure mp-units CMake if: matrix.config.compiler.type != 'VISUAL' shell: bash working-directory: build/${{ matrix.build_type }} run: | - cmake ../../src -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake + cmake ../../src -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} - name: Install mp-units shell: bash working-directory: build/${{ matrix.build_type }} @@ -208,14 +224,14 @@ jobs: working-directory: test_package/build/${{ matrix.build_type }} run: | call conanvcvars.bat - cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -Dmp-units_DIR=${{ github.workspace }}/build/${{ matrix.build_type }} + cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -Dmp-units_DIR=${{ github.workspace }}/build/${{ matrix.build_type }} cmake --build . - name: Build test_package CMake (local build) if: matrix.config.compiler.type != 'VISUAL' shell: bash working-directory: test_package/build/${{ matrix.build_type }} run: | - cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -Dmp-units_DIR=${{ github.workspace }}/build/${{ matrix.build_type }} + cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -Dmp-units_DIR=${{ github.workspace }}/build/${{ matrix.build_type }} cmake --build . - name: Build test_package CMake (installation) if: matrix.config.compiler.type == 'VISUAL' @@ -223,14 +239,14 @@ jobs: working-directory: test_package/build/${{ matrix.build_type }} run: | call conanvcvars.bat - cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_INSTALL_PREFIX=../../../build/${{ matrix.build_type }}/test_package + cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_INSTALL_PREFIX=../../../build/${{ matrix.build_type }}/test_package cmake --build . - name: Build test_package CMake (installation) if: matrix.config.compiler.type != 'VISUAL' shell: bash working-directory: test_package/build/${{ matrix.build_type }} run: | - cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_INSTALL_PREFIX=../../../build/${{ matrix.build_type }}/test_package + cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_INSTALL_PREFIX=../../../build/${{ matrix.build_type }}/test_package cmake --build . - name: Run test_package shell: bash diff --git a/.gitignore b/.gitignore index 751b2745..a4547914 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,9 @@ /out/ _build/ +# CMake +CMakeUserPresets.json + # Conan *.pyc /test_package/build/ diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile index d944277b..49164bc2 100644 --- a/.gitpod.Dockerfile +++ b/.gitpod.Dockerfile @@ -3,10 +3,12 @@ FROM trainiteu/gitpod-cpp # Add clang-12 and clang-15 apt repositories RUN lsb_rel=`lsb_release -cs` \ && sudo add-apt-repository "deb http://apt.llvm.org/${lsb_rel}/ llvm-toolchain-${lsb_rel}-12 main" \ + && sudo add-apt-repository "deb http://apt.llvm.org/${lsb_rel}/ llvm-toolchain-${lsb_rel}-13 main" \ && sudo add-apt-repository "deb http://apt.llvm.org/${lsb_rel}/ llvm-toolchain-${lsb_rel} main" # Install older compilers supported by the project as well as clang-format-15 for code formatting RUN sudo install-packages \ g++-10 \ clang-12 \ + clang-13 \ clang-format-15 diff --git a/.gitpod.yml b/.gitpod.yml index 68f2d92e..fe00fec5 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -84,6 +84,7 @@ tasks: cp default gcc11 cp default clang12 cp default clang13 + cp default clang14 popd conan profile update settings.compiler.version=10 gcc10 conan profile update env.CXX=/usr/bin/g++-10 gcc10 @@ -95,9 +96,14 @@ tasks: conan profile update env.CC=/usr/bin/clang-12 clang12 conan profile update settings.compiler=clang clang13 conan profile update settings.compiler.version=13 clang13 - conan profile update settings.compiler.libcxx=libc++ clang13 + conan profile update settings.compiler.libcxx=libstdc++11 clang13 conan profile update env.CXX=/usr/bin/clang++-13 clang13 conan profile update env.CC=/usr/bin/clang-13 clang13 + conan profile update settings.compiler=clang clang14 + conan profile update settings.compiler.version=14 clang14 + conan profile update settings.compiler.libcxx=libc++ clang14 + conan profile update env.CXX=/usr/bin/clang++-14 clang14 + conan profile update env.CC=/usr/bin/clang-14 clang14 gp sync-done conan-init exit - name: gcc-10 @@ -149,6 +155,18 @@ tasks: ctest -C Release ctest -C Debug echo "🛠️ clang-13 pre-build done! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️" + - name: clang-14 + init: | + gp sync-await conan-init + mkdir -p build/Clang-14 && cd build/Clang-14 + conan install ../.. -pr clang4 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated + conan install ../.. -pr clang14 -e mp-units:CONAN_RUN_TESTS=True -o build_docs=False -b outdated -s build_type=Debug + cmake ../.. --no-warn-unused-cli --toolchain conan_toolchain.cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=TRUE -DCMAKE_C_COMPILER=/usr/bin/clang-14 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-14 + cmake --build . --config Release -j + cmake --build . --config Debug -j + ctest -C Release + ctest -C Debug + echo "🛠️ clang-14 pre-build done! You can close this terminal and use 'Build' button in the VSCode status bar for incremental builds. 🛠️" - name: documentation init: | gp sync-await conan-init diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 90919c87..1a890db6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ default_stages: [commit] repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.1.0 + rev: v4.2.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer @@ -16,5 +16,19 @@ repos: - id: cmake-format additional_dependencies: ["cmakelang[YAML]"] # - id: cmake-lint - # additional_dependencies: ["cmakelang"] - # exclude: "cmake/.*" + # additional_dependencies: ["cmakelang"] + # exclude: "cmake/.*" + - repo: https://github.com/psf/black + rev: 22.3.0 + hooks: + - id: black + language_version: python3 + - repo: https://github.com/PyCQA/isort + rev: 5.10.1 + hooks: + - id: isort + args: [--profile, black, --multi-line, "3"] + - repo: https://github.com/PyCQA/flake8 + rev: 4.0.1 + hooks: + - id: flake8 diff --git a/CMakeLists.txt b/CMakeLists.txt index e3626289..f0ca1045 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) project(mp-units-dev LANGUAGES CXX) list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") @@ -71,3 +71,7 @@ add_subdirectory(docs) # add unit tests enable_testing() add_subdirectory(test) + +# tests for standalone headers +include(TestPublicHeaders) +add_public_header_test(test_headers mp-units::mp-units) diff --git a/build.py b/build.py index c733eb38..e3bc1a56 100644 --- a/build.py +++ b/build.py @@ -31,16 +31,14 @@ from cpt.packager import ConanMultiPackager if __name__ == "__main__": builder = ConanMultiPackager( # package id - channel = "testing", - stable_branch_pattern = r"v\d+\.\d+\.\d+.*", - + channel="testing", + stable_branch_pattern=r"v\d+\.\d+\.\d+.*", # dependencies - build_policy = ["mp-units", "outdated"], - upload_dependencies = "all", - pip_install = ["sphinx", "recommonmark", "breathe"], - + build_policy=["mp-units", "outdated"], + upload_dependencies="all", + pip_install=["sphinx", "recommonmark", "breathe"], # build configurations - archs = ["x86_64"], # limit to 64-bit only + archs=["x86_64"], # limit to 64-bit only ) builder.add_common_builds(pure_c=True) for settings, options, env_vars, build_requires, reference in builder.items: diff --git a/cmake/TestHeaders.cmake b/cmake/TestHeaders.cmake new file mode 100644 index 00000000..6ec30990 --- /dev/null +++ b/cmake/TestHeaders.cmake @@ -0,0 +1,129 @@ +# Copyright Louis Dionne 2013-2017 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) +# +# +# This CMake module provides a function generating a unit test to make sure +# that every public header can be included on its own. +# +# When a C++ library or application has many header files, it can happen that +# a header does not include all the other headers it depends on. When this is +# the case, it can happen that including that header file on its own will +# break the compilation. This CMake module generates a dummy executable +# comprised of many .cpp files, each of which includes a header file that +# is part of the public API. In other words, the executable is comprised +# of .cpp files of the form: +# +# #include +# +# and then exactly one `main` function. If this succeeds to compile, it means +# that the header can be included on its own, which is what clients expect. +# Otherwise, you have a problem. Since writing these dumb unit tests by hand +# is tedious and repetitive, you can use this CMake module to automate this +# task. + +# add_header_test( [EXCLUDE_FROM_ALL] [EXCLUDE excludes...] HEADERS headers...) +# +# Generates header-inclusion unit tests for all the specified headers. +# +# This function creates a target which builds a dummy executable including +# each specified header file individually. If this target builds successfully, +# it means that all the specified header files can be included individually. +# +# Parameters +# ---------- +# : +# The name of the target to generate. +# +# HEADERS headers: +# A list of header files to generate the inclusion tests for. All headers +# in this list must be represented as relative paths from the root of the +# include directory added to the compiler's header search path. In other +# words, it should be possible to include all headers in this list as +# +# #include <${header}> +# +# For example, for a library with the following structure: +# +# project/ +# doc/ +# test/ +# ... +# include/ +# boost/ +# hana.hpp +# hana/ +# transform.hpp +# tuple.hpp +# pair.hpp +# ... +# +# When building the unit tests for that library, we'll add `-I project/include' +# to the compiler's arguments. The list of public headers should therefore contain +# +# boost/hana.hpp +# boost/hana/transform.hpp +# boost/hana/tuple.hpp +# boost/hana/pair.hpp +# ... +# +# Usually, all the 'public' header files of a library should be tested for +# standalone inclusion. A header is considered 'public' if a client should +# be able to include that header on its own. +# +# [EXCLUDE excludes]: +# An optional list of headers or regexes for which no unit test should be +# generated. Basically, any header in the list specified by the `HEADERS` +# argument that matches anything in `EXCLUDE` will be skipped. +# +# [EXCLUDE_FROM_ALL]: +# If provided, the generated target is excluded from the 'all' target. +# +function(add_header_test target) + cmake_parse_arguments( + ARGS + "EXCLUDE_FROM_ALL" # options + "" # 1 value args + "HEADERS;EXCLUDE" # multivalued args + ${ARGN} + ) + if(NOT ARGS_HEADERS) + message(FATAL_ERROR "The `HEADERS` argument must be provided.") + endif() + + if(ARGS_EXCLUDE_FROM_ALL) + set(ARGS_EXCLUDE_FROM_ALL "EXCLUDE_FROM_ALL") + else() + set(ARGS_EXCLUDE_FROM_ALL "") + endif() + + foreach(header ${ARGS_HEADERS}) + set(skip FALSE) + foreach(exclude ${ARGS_EXCLUDE}) + if(${header} MATCHES ${exclude}) + set(skip TRUE) + break() + endif() + endforeach() + if(skip) + continue() + endif() + + get_filename_component(filename "${header}" NAME_WE) + get_filename_component(directory "${header}" DIRECTORY) + + set(source "${CMAKE_CURRENT_BINARY_DIR}/headers/${directory}/${filename}.cpp") + if(NOT EXISTS "${source}") + file(WRITE "${source}" "#include <${header}>") + endif() + list(APPEND sources "${source}") + endforeach() + + set(standalone_main "${CMAKE_CURRENT_BINARY_DIR}/headers/_standalone_main.cpp") + if(NOT EXISTS "${standalone_main}") + file(WRITE "${standalone_main}" "int main() { }") + endif() + add_executable( + ${target} ${ARGS_EXCLUDE_FROM_ALL} ${sources} "${CMAKE_CURRENT_BINARY_DIR}/headers/_standalone_main.cpp" + ) +endfunction() diff --git a/cmake/TestPublicHeaders.cmake b/cmake/TestPublicHeaders.cmake new file mode 100644 index 00000000..e1756af5 --- /dev/null +++ b/cmake/TestPublicHeaders.cmake @@ -0,0 +1,67 @@ +# The MIT License (MIT) +# +# Copyright (c) 2018 Mateusz Pusz +# +# 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. + +cmake_minimum_required(VERSION 3.19) + +function(get_target_linked_targets target targets_out) + get_target_property(linked_libs ${target} INTERFACE_LINK_LIBRARIES) + foreach(linked_lib ${linked_libs}) + if(NOT linked_lib IN_LIST targets) + if(TARGET ${linked_lib}) + get_target_linked_targets(${linked_lib} child_targets) + list(APPEND targets ${linked_lib} ${child_targets}) + endif() + endif() + endforeach() + + list(REMOVE_DUPLICATES targets) + list(REMOVE_DUPLICATES link_libs) + set(${targets_out} ${targets} PARENT_SCOPE) +endfunction() + +function(get_target_sources target paths_out) + get_target_linked_targets(${target} targets) + list(APPEND targets ${target}) + + foreach(t ${targets}) + get_target_property(sources ${t} SOURCES) + if(sources) + get_target_property(source_dir ${t} SOURCE_DIR) + foreach(f ${sources}) + file(REAL_PATH "${f}" path BASE_DIRECTORY "${source_dir}") + file(RELATIVE_PATH path ${CMAKE_CURRENT_LIST_DIR} "${path}") + list(APPEND paths "${path}") + endforeach() + endif() + endforeach() + + set(${paths_out} ${paths} PARENT_SCOPE) +endfunction() + +include(TestHeaders) + +function(add_public_header_test target test_target) + get_target_sources(${test_target} sources) + add_header_test(${target} HEADERS ${sources}) + target_link_libraries(${target} PRIVATE ${test_target}) + target_include_directories(${target} PRIVATE .) +endfunction() diff --git a/conanfile.py b/conanfile.py index 924700cb..a673412e 100644 --- a/conanfile.py +++ b/conanfile.py @@ -20,67 +20,88 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from conans import ConanFile, tools -from conans.tools import Version, check_min_cppstd -from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake -from conans.errors import ConanInvalidConfiguration -import os, re +import os +import re + +from conan import ConanFile +from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain +from conan.tools.files import copy, load, rmdir +from conan.tools.scm import Version +from conans.errors import ConanInvalidConfiguration + +# TODO replace with new tools for Conan 2.0 +from conans.tools import check_min_cppstd, get_env + +required_conan_version = ">=1.48.0" -required_conan_version = ">=1.44.0" class MPUnitsConan(ConanFile): name = "mp-units" homepage = "https://github.com/mpusz/units" description = "Physical Units library for C++" - topics = ("units", "dimensions", "quantities", "dimensional-analysis", "physical-quantities", "physical-units", "system-of-units", "cpp23", "cpp20", "library", "quantity-manipulation") + topics = ( + "units", + "dimensions", + "quantities", + "dimensional-analysis", + "physical-quantities", + "physical-units", + "system-of-units", + "cpp23", + "cpp20", + "library", + "quantity-manipulation", + ) license = "MIT" url = "https://github.com/mpusz/units" settings = "os", "compiler", "build_type", "arch" - requires = ( - "gsl-lite/0.38.1" - ) - options = { - "downcast_mode": ["off", "on", "auto"], - "build_docs": [True, False] - } - default_options = { - "downcast_mode": "on", - "build_docs": True - } + requires = "gsl-lite/0.40.0" + options = {"downcast_mode": ["off", "on", "auto"], "build_docs": [True, False]} + default_options = {"downcast_mode": "on", "build_docs": True} exports = ["LICENSE.md"] - exports_sources = ["docs/*", "src/*", "test/*", "cmake/*", "example/*","CMakeLists.txt"] + exports_sources = [ + "docs/*", + "src/*", + "test/*", + "cmake/*", + "example/*", + "CMakeLists.txt", + ] + no_copy_source = True generators = "cmake_paths" @property def _run_tests(self): - return tools.get_env("CONAN_RUN_TESTS", False) + return get_env("CONAN_RUN_TESTS", False) @property def _use_libfmt(self): compiler = self.settings.compiler version = Version(self.settings.compiler.version) - std_support = \ - (compiler == "Visual Studio" and version >= 17 and compiler.cppstd == 23) or \ - (compiler == "msvc" and version >= 193 and compiler.cppstd == 23) + std_support = ( + compiler == "Visual Studio" and version >= 17 and compiler.cppstd == 23 + ) or (compiler == "msvc" and version >= 193 and compiler.cppstd == 23) return not std_support @property def _use_range_v3(self): compiler = self.settings.compiler version = Version(self.settings.compiler.version) - return ("clang" in compiler and compiler.libcxx == "libc++" and version < 14) + return "clang" in compiler and compiler.libcxx == "libc++" and version < 14 @property def _msvc_version(self): compiler = self.settings.compiler - if (compiler.update): + if compiler.update: return int(f"{compiler.version}{compiler.update}") else: return int(f"{compiler.version}0") def set_version(self): - content = tools.load(os.path.join(self.recipe_folder, "src/CMakeLists.txt")) - version = re.search(r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content).group(1) + content = load(self, os.path.join(self.recipe_folder, "src/CMakeLists.txt")) + version = re.search( + r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content + ).group(1) self.version = version.strip() def requirements(self): @@ -92,12 +113,13 @@ class MPUnitsConan(ConanFile): def build_requirements(self): if self._run_tests: - self.test_requires("catch2/2.13.7") + self.test_requires("catch2/2.13.9") self.test_requires("wg21-linear_algebra/0.7.2") if self.options.build_docs: - self.tool_requires("doxygen/1.9.2") + self.tool_requires("doxygen/1.9.4") - def validate(self): + # TODO Replace with `valdate()` for Conan 2.0 (https://github.com/conan-io/conan/issues/10723) + def configure(self): compiler = self.settings.compiler version = Version(self.settings.compiler.version) if compiler == "gcc": @@ -108,10 +130,14 @@ class MPUnitsConan(ConanFile): raise ConanInvalidConfiguration("mp-units requires at least clang++-12") elif compiler == "apple-clang": if version < 13: - raise ConanInvalidConfiguration("mp-units requires at least AppleClang 13") + raise ConanInvalidConfiguration( + "mp-units requires at least AppleClang 13" + ) elif compiler == "Visual Studio": if version < 16: - raise ConanInvalidConfiguration("mp-units requires at least Visual Studio 16.9") + raise ConanInvalidConfiguration( + "mp-units requires at least Visual Studio 16.9" + ) elif compiler == "msvc": if self._msvc_version < 1928: raise ConanInvalidConfiguration("mp-units requires at least MSVC 19.28") @@ -146,16 +172,22 @@ class MPUnitsConan(ConanFile): self.info.header_only() def package(self): - self.copy("LICENSE.md", dst="licenses") + copy( + self, + "LICENSE.md", + self.source_folder, + os.path.join(self.package_folder, "licenses"), + ) cmake = CMake(self) cmake.install() - tools.rmdir(os.path.join(self.package_folder, "lib", "cmake")) + rmdir(self, os.path.join(self.package_folder, "lib", "cmake")) def package_info(self): compiler = self.settings.compiler # core self.cpp_info.components["core"].requires = ["gsl-lite::gsl-lite"] + self.cpp_info.components["core"].includedirs = ["include"] if compiler == "Visual Studio": self.cpp_info.components["core"].cxxflags = ["/utf-8"] if self._use_range_v3: @@ -163,19 +195,60 @@ class MPUnitsConan(ConanFile): # rest self.cpp_info.components["core-io"].requires = ["core"] + self.cpp_info.components["core-io"].includedirs = ["include"] + self.cpp_info.components["core-fmt"].requires = ["core"] + self.cpp_info.components["core-fmt"].includedirs = ["include"] if self._use_libfmt: self.cpp_info.components["core-fmt"].requires.append("fmt::fmt") + self.cpp_info.components["isq"].requires = ["core"] + self.cpp_info.components["isq"].includedirs = ["include"] + self.cpp_info.components["isq-natural"].requires = ["isq"] + self.cpp_info.components["isq-natural"].includedirs = ["include"] + self.cpp_info.components["si"].requires = ["isq"] + self.cpp_info.components["si"].includedirs = ["include"] + self.cpp_info.components["si-cgs"].requires = ["si"] - self.cpp_info.components["si-fps"].requires = ["si"] + self.cpp_info.components["si-cgs"].includedirs = ["include"] + + self.cpp_info.components["si-fps"].requires = ["si-international"] + self.cpp_info.components["si-fps"].includedirs = ["include"] + self.cpp_info.components["si-hep"].requires = ["si"] + self.cpp_info.components["si-hep"].includedirs = ["include"] + self.cpp_info.components["si-iau"].requires = ["si"] + self.cpp_info.components["si-iau"].includedirs = ["include"] + self.cpp_info.components["si-imperial"].requires = ["si"] + self.cpp_info.components["si-imperial"].includedirs = ["include"] + self.cpp_info.components["si-international"].requires = ["si"] + self.cpp_info.components["si-international"].includedirs = ["include"] + self.cpp_info.components["si-typographic"].requires = ["si"] + self.cpp_info.components["si-typographic"].includedirs = ["include"] + self.cpp_info.components["si-uscs"].requires = ["si"] + self.cpp_info.components["si-uscs"].includedirs = ["include"] + self.cpp_info.components["isq-iec80000"].requires = ["si"] - self.cpp_info.components["systems"].requires = ["isq", "isq-natural", "si", "si-cgs", "si-fps", "si-hep", "si-iau", "si-imperial", "si-international", "si-typographic", "si-uscs", "isq-iec80000"] + self.cpp_info.components["isq-iec80000"].includedirs = ["include"] + + self.cpp_info.components["systems"].requires = [ + "isq", + "isq-natural", + "si", + "si-cgs", + "si-fps", + "si-hep", + "si-iau", + "si-imperial", + "si-international", + "si-typographic", + "si-uscs", + "isq-iec80000", + ] diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 2982bbea..fc803b52 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -2,18 +2,60 @@ - **0.8.0 WIP** - (!) refactor: `common_quantity`, `common_quantity_for`, `common_quantity_point`, `common_quantity_kind`, and `common_quantity_point_kind` removed + - (!) refactor: `named_derived_unit` removed as it was not used + - (!) refactor: `derived_unit` renamed to `derived_scaled_unit` + - (!) refactor: `unit` renamed to `derived_unit` + - (!) refactor: `U::is_named` removed from the unit types and replaced with `NamedUnit` concept + - (!) refactor: `PrefixFamily` support removed + - (!) refactor: `mi(naut)` renamed to `nmi` + - (!) refactor: `knot` unit helper renamed to `kn` in FPS + - (!) refactor: `knot` text symbol changed from `"knot"` to `"kn`" - refactor: `quantity` `op+()` and `op-()` reimplemented in terms of `reference` rather then `quantity` types - - feat: `std::format` support for compliant compilers added + - refactor(example): `glide_computer` now use dimensionless quantities with `ranged_representation` as `rep` - feat: HEP system support added (thanks [@RalphSteinhagen](https://github.com/RalphSteinhagen)) + - feat: `floor()`, `ceil()`, and `round()` support added (thanks [@hofbi](https://github.com/hofbi)) + - feat: `std::format` support for compliant compilers added - feat: conversion helpers from `mp-units` to `std::chrono` types added + - feat: math functions can now be safely used with user-defined types + - feat: conversion from `quantity_point` to `std::chrono::time_point` added + - feat: `nautical_mile_per_hour` and `knot` added to `si::international` system - (!) fix: add `quantity_point::origin`, like `std::chrono::time_point::clock` + - fix: enable any prefixes for most of the named units (beside those that use prefixes already) + - fix: `hectare` definition fixed to be a prefixed version of `are` + other units - fix: account for different dimensions in `quantity_point_cast`'s constraint - - build: Minimum Conan version changed to 1.40 + - fix: output stream operator now properly handles state + - fix: `fmt` algorithms were overconstrained with `forward_iterator` + - fix: CTAD for aliases fixed + - fix: `derived_ratio` calculation + - fix: `fill_t` assignment operator fixed + - fix: improve downcast mode off + - fix: `radioactivity` header compilation fixed + - fix: `si::hep::dim_momentum` duplicated definition fixed + - fix: `fps` can now coexist with `international` system + - fix: public headers fixed to be standalone + - test: standalone public headers tests added + - (!) build: CMake generator in Conan is no longer obtained from an environment variable + - (!) build: Required Conan version bumped to 1.48 + - (!) build: Conan 1.48 does not set `CMAKE_BUILD_TYPE` in the `conan_toolchain.cmake` anymore + - build: AppleClang 13 support added (thanks [@fdischner](https://github.com/fdischner)) + - build: most of the `conanfile.py` refactored to be Conan 2.0 ready + - build: `validate()` replaced with `configure()` to raise errors during `conan install` in Conan 1.X + - build: minimum Conan version changed to 1.40 + - build: `linear-algebra` Conan repo is no needed anymore + - build: Gitpod support added + - build: clang-format-15 support added + - build: export config to local build (#322) + - build: fix export name of `mp-units-system` - build: fmt updated to 8.0.1 - - build: gsl-lite updated to 0.38.1 - - build: catch2 updated to 2.13.7 - - build: doxygen updated to 1.9.2 - - build: linear algebra switched to wg21-linear_algebra/0.7.2 + - build: gsl-lite updated to 0.40.0 + - build: catch2 updated to 2.13.9 + - build: doxygen updated to 1.9.4 + - build: linear_algebra/0.7.0 switched to wg21-linear_algebra/0.7.2 + - ci: VS2022, gcc-11, clang-13, clang-14, and AppleClang 13 support added + - ci: pre-commit support added (thanks [@hofbi](https://github.com/hofbi)) + - docs: Project documentation updated + - docs: `CITATION.cff` file added + - docs: `CONTRIBUTING.md` updated - **0.7.0 May 11, 2021** - (!) refactor: `ScalableNumber` renamed to `Representation` diff --git a/docs/_static/img/units.svg b/docs/_static/img/units.svg index 59002174..c19aae88 100644 --- a/docs/_static/img/units.svg +++ b/docs/_static/img/units.svg @@ -1,122 +1,158 @@ -Unitprefix_familyno_prefixprefixPrefixFamily, Symbol, Ratioscaled_unitUnitRatio, Unitprefixed_alias_unitUnit, Prefix, AliasUnitalias_unitUnit, Symbol, PrefixFamilynamed_derived_unitDimension, Symbol, PrefixFamily, Unit, Unit...derived_unitDimension, Unit, Unit...prefixed_unitPrefix, Unitnamed_scaled_unitSymbol, PrefixFamily, Ratio, Unitnamed_unitSymbol, PrefixFamilyunit + + + + + Unit + + + + + scaled_unit + + UnitRatio, Unit + + + + + prefixed_alias_unit + + Unit, Prefix, AliasUnit + + + + + + alias_unit + + Unit, Symbol + + + + + + derived_scaled_unit + + Dimension, Unit, Unit... + + + + + + derived_unit + + + + + + prefixed_unit + + Prefix, Unit + + + + + + named_scaled_unit + + Symbol, Ratio, Unit + + + + + + named_unit + + Symbol + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--> + + diff --git a/docs/conf.py b/docs/conf.py index 382ae080..54aa719b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -9,155 +9,315 @@ :license: BSD, see LICENSE for details. """ +import os import re -import sphinx_rtd_theme +import subprocess -from pygments.lexer import RegexLexer, include, bygroups, using, \ - this, inherit, default, words +from pygments.lexer import ( + RegexLexer, + bygroups, + default, + include, + inherit, + this, + using, + words, +) +from pygments.token import ( + Comment, + Error, + Keyword, + Name, + Number, + Operator, + Punctuation, + String, + Text, +) from pygments.util import get_bool_opt -from pygments.token import Text, Comment, Operator, Keyword, Name, String, \ - Number, Punctuation, Error from sphinx.highlighting import lexers + class MyCFamilyLexer(RegexLexer): #: optional Comment or Whitespace - _ws = r'(?:\s|//.*?\n|/[*].*?[*]/)+' + _ws = r"(?:\s|//.*?\n|/[*].*?[*]/)+" # The trailing ?, rather than *, avoids a geometric performance drop here. #: only one /* */ style comment - _ws1 = r'\s*(?:/[*].*?[*]/\s*)?' + _ws1 = r"\s*(?:/[*].*?[*]/\s*)?" tokens = { - 'whitespace': [ + "whitespace": [ # preprocessor directives: without whitespace - (r'^#if\s+0', Comment.Preproc, 'if0'), - ('^#', Comment.Preproc, 'macro'), + (r"^#if\s+0", Comment.Preproc, "if0"), + ("^#", Comment.Preproc, "macro"), # or with whitespace - ('^(' + _ws1 + r')(#if\s+0)', - bygroups(using(this), Comment.Preproc), 'if0'), - ('^(' + _ws1 + ')(#)', - bygroups(using(this), Comment.Preproc), 'macro'), - (r'\n', Text), - (r'\s+', Text), - (r'\\\n', Text), # line continuation - (r'//(\n|[\w\W]*?[^\\]\n)', Comment.Single), - (r'/(\\\n)?[*][\w\W]*?[*](\\\n)?/', Comment.Multiline), + ( + "^(" + _ws1 + r")(#if\s+0)", + bygroups(using(this), Comment.Preproc), + "if0", + ), + ("^(" + _ws1 + ")(#)", bygroups(using(this), Comment.Preproc), "macro"), + (r"\n", Text), + (r"\s+", Text), + (r"\\\n", Text), # line continuation + (r"//(\n|[\w\W]*?[^\\]\n)", Comment.Single), + (r"/(\\\n)?[*][\w\W]*?[*](\\\n)?/", Comment.Multiline), # Open until EOF, so no ending delimeter - (r'/(\\\n)?[*][\w\W]*', Comment.Multiline), + (r"/(\\\n)?[*][\w\W]*", Comment.Multiline), ], - 'statements': [ - (r'(L?)(")', bygroups(String.Affix, String), 'string'), - (r"(L?)(')(\\.|\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,2}|[^\\\'\n])(')", - bygroups(String.Affix, String.Char, String.Char, String.Char)), - (r'\*/', Error), - (r'[~!%^&*+=|?:<>/-]', Operator), - (r'[()\[\],.]', Punctuation), - (words(('asm', 'auto', 'break', 'case', 'const', 'continue', - 'default', 'do', 'else', 'enum', 'extern', 'for', 'goto', - 'if', 'register', 'restricted', 'return', 'sizeof', - 'static', 'struct', 'switch', 'typedef', 'union', - 'volatile', 'while'), - suffix=r'\b'), Keyword), - (r'(bool|int|long|float|short|double|char|unsigned|signed|void)\b', - Keyword.Type), - (words(('inline', '_inline', '__inline', 'naked', 'restrict', - 'thread', 'typename'), suffix=r'\b'), Keyword.Reserved), + "statements": [ + (r'(L?)(")', bygroups(String.Affix, String), "string"), + ( + r"(L?)(')(\\.|\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,2}|[^\\\'\n])(')", + bygroups(String.Affix, String.Char, String.Char, String.Char), + ), + (r"\*/", Error), + (r"[~!%^&*+=|?:<>/-]", Operator), + (r"[()\[\],.]", Punctuation), + ( + words( + ( + "asm", + "auto", + "break", + "case", + "const", + "continue", + "default", + "do", + "else", + "enum", + "extern", + "for", + "goto", + "if", + "register", + "restricted", + "return", + "sizeof", + "static", + "struct", + "switch", + "typedef", + "union", + "volatile", + "while", + ), + suffix=r"\b", + ), + Keyword, + ), + ( + r"(bool|int|long|float|short|double|char|unsigned|signed|void)\b", + Keyword.Type, + ), + ( + words( + ( + "inline", + "_inline", + "__inline", + "naked", + "restrict", + "thread", + "typename", + ), + suffix=r"\b", + ), + Keyword.Reserved, + ), # Vector intrinsics - (r'(__m(128i|128d|128|64))\b', Keyword.Reserved), + (r"(__m(128i|128d|128|64))\b", Keyword.Reserved), # Microsoft-isms - (words(( - 'asm', 'int8', 'based', 'except', 'int16', 'stdcall', 'cdecl', - 'fastcall', 'int32', 'declspec', 'finally', 'int64', 'try', - 'leave', 'wchar_t', 'w64', 'unaligned', 'raise', 'noop', - 'identifier', 'forceinline', 'assume'), - prefix=r'__', suffix=r'\b'), Keyword.Reserved), - (r'(true|false|NULL)\b', Name.Builtin), - (r'([a-zA-Z_]\w*)(\s*)(:)(?!:)', bygroups(Name.Label, Text, Punctuation)), - (r'[a-zA-Z_]\w*', Name), + ( + words( + ( + "asm", + "int8", + "based", + "except", + "int16", + "stdcall", + "cdecl", + "fastcall", + "int32", + "declspec", + "finally", + "int64", + "try", + "leave", + "wchar_t", + "w64", + "unaligned", + "raise", + "noop", + "identifier", + "forceinline", + "assume", + ), + prefix=r"__", + suffix=r"\b", + ), + Keyword.Reserved, + ), + (r"(true|false|NULL)\b", Name.Builtin), + (r"([a-zA-Z_]\w*)(\s*)(:)(?!:)", bygroups(Name.Label, Text, Punctuation)), + (r"[a-zA-Z_]\w*", Name), ], - 'root': [ - include('whitespace'), + "root": [ + include("whitespace"), # functions - (r'((?:[\w*\s])+?(?:\s|[*]))' # return arguments - r'([a-zA-Z_]\w*)' # method name - r'(\s*\([^;]*?\))' # signature - r'([^;{]*)(\{)', - bygroups(using(this), Name.Function, using(this), using(this), - Punctuation), - 'function'), + ( + r"((?:[\w*\s])+?(?:\s|[*]))" # return arguments + r"([a-zA-Z_]\w*)" # method name + r"(\s*\([^;]*?\))" # signature + r"([^;{]*)(\{)", + bygroups( + using(this), Name.Function, using(this), using(this), Punctuation + ), + "function", + ), # function declarations - (r'((?:[\w*\s])+?(?:\s|[*]))' # return arguments - r'([a-zA-Z_]\w*)' # method name - r'(\s*\([^;]*?\))' # signature - r'([^;]*)(;)', - bygroups(using(this), Name.Function, using(this), using(this), - Punctuation)), - default('statement'), + ( + r"((?:[\w*\s])+?(?:\s|[*]))" # return arguments + r"([a-zA-Z_]\w*)" # method name + r"(\s*\([^;]*?\))" # signature + r"([^;]*)(;)", + bygroups( + using(this), Name.Function, using(this), using(this), Punctuation + ), + ), + default("statement"), ], - 'statement': [ - include('whitespace'), - include('statements'), - ('[{}]', Punctuation), - (';', Punctuation, '#pop'), + "statement": [ + include("whitespace"), + include("statements"), + ("[{}]", Punctuation), + (";", Punctuation, "#pop"), ], - 'function': [ - include('whitespace'), - include('statements'), - (';', Punctuation), - (r'\{', Punctuation, '#push'), - (r'\}', Punctuation, '#pop'), + "function": [ + include("whitespace"), + include("statements"), + (";", Punctuation), + (r"\{", Punctuation, "#push"), + (r"\}", Punctuation, "#pop"), ], - 'string': [ - (r'"', String, '#pop'), - (r'\\([\\abfnrtv"\']|x[a-fA-F0-9]{2,4}|' - r'u[a-fA-F0-9]{4}|U[a-fA-F0-9]{8}|[0-7]{1,3})', String.Escape), + "string": [ + (r'"', String, "#pop"), + ( + r'\\([\\abfnrtv"\']|x[a-fA-F0-9]{2,4}|' + r"u[a-fA-F0-9]{4}|U[a-fA-F0-9]{8}|[0-7]{1,3})", + String.Escape, + ), (r'[^\\"\n]+', String), # all other characters - (r'\\\n', String), # line continuation - (r'\\', String), # stray backslash + (r"\\\n", String), # line continuation + (r"\\", String), # stray backslash ], - 'macro': [ - (r'(include)(' + _ws1 + r')([^\n]+)', - bygroups(Comment.Preproc, Text, Comment.PreprocFile)), - (r'[^/\n]+', Comment.Preproc), - (r'/[*](.|\n)*?[*]/', Comment.Multiline), - (r'//.*?\n', Comment.Single, '#pop'), - (r'/', Comment.Preproc), - (r'(?<=\\)\n', Comment.Preproc), - (r'\n', Comment.Preproc, '#pop'), + "macro": [ + ( + r"(include)(" + _ws1 + r")([^\n]+)", + bygroups(Comment.Preproc, Text, Comment.PreprocFile), + ), + (r"[^/\n]+", Comment.Preproc), + (r"/[*](.|\n)*?[*]/", Comment.Multiline), + (r"//.*?\n", Comment.Single, "#pop"), + (r"/", Comment.Preproc), + (r"(?<=\\)\n", Comment.Preproc), + (r"\n", Comment.Preproc, "#pop"), + ], + "if0": [ + (r"^\s*#if.*?(?)', Text, '#pop'), + (r"\s*(?=>)", Text, "#pop"), ], } def analyse_text(text): - if re.search('#include <[a-z_]+>', text): + if re.search("#include <[a-z_]+>", text): return 0.2 - if re.search('using namespace ', text): + if re.search("using namespace ", text): return 0.4 -lexers['cpp'] = MyCppLexer(startinline=True) + +lexers["cpp"] = MyCppLexer(startinline=True) # TODO Remove the above when Pygments release with fixes is available @@ -241,13 +483,14 @@ lexers['cpp'] = MyCppLexer(startinline=True) # For a full list see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html -import subprocess, os, re def get_version(): try: - with open('../src/CMakeLists.txt', 'r') as file: + with open("../src/CMakeLists.txt", "r") as file: content = file.read() - version = re.search(r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content).group(1) + version = re.search( + r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content + ).group(1) return version.strip() except Exception: return None @@ -255,9 +498,9 @@ def get_version(): # -- Project information ----------------------------------------------------- -project = 'mp-units' -copyright = '2018-present, Mateusz Pusz' -author = 'Mateusz Pusz' +project = "mp-units" +copyright = "2018-present, Mateusz Pusz" +author = "Mateusz Pusz" # The major project version, used as the replacement for |version|. version = get_version() @@ -270,21 +513,21 @@ release = get_version() # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autosectionlabel', - 'sphinx.ext.githubpages', - 'sphinx.ext.graphviz', - 'sphinx_rtd_theme', - 'recommonmark', - 'breathe' + "sphinx.ext.autosectionlabel", + "sphinx.ext.githubpages", + "sphinx.ext.graphviz", + "sphinx_rtd_theme", + "recommonmark", + "breathe", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # If true, Sphinx will warn about all references where the target cannot # be found. Default is False. @@ -305,29 +548,29 @@ autosectionlabel_prefix_document = True # The name of the default domain. Can also be None to disable a default # domain. The default is 'py'. -primary_domain = 'cpp' +primary_domain = "cpp" # The reST default role (used for this markup: `text`) to use for all documents. -default_role = 'cpp:any' +default_role = "cpp:any" # The default language to highlight source code in. The default is 'python3'. # The value should be a valid Pygments lexer name (https://pygments.org/docs/lexers). -highlight_language = 'cpp' +highlight_language = "cpp" # The style name to use for Pygments highlighting of source code. If not set, # either the theme’s default style or 'sphinx' is selected for HTML output. -pygments_style = 'default' +pygments_style = "default" # A list of prefixes that will be ignored when sorting C++ objects in the global # index. For example ['awesome_lib::']. -cpp_index_common_prefix = ['units::'] +cpp_index_common_prefix = ["units::"] # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'sphinx_rtd_theme' +html_theme = "sphinx_rtd_theme" # A dictionary of options that influence the look and feel of the selected theme. # These are theme-specific. @@ -339,7 +582,7 @@ html_theme_options = { # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # If given, this must be the name of an image file (path relative to the # configuration directory) that is the logo of the docs. It is placed at the @@ -349,45 +592,45 @@ html_static_path = ['_static'] # These paths are either relative to html_static_path or fully qualified # paths (eg. https://...) -html_css_files = [ - 'css/custom.css' -] +html_css_files = ["css/custom.css"] # -- Breathe configuration --------------------------------------------------- + def configureDoxyfile(input_dir, output_dir): - with open('Doxyfile.in', 'r') as file: + with open("Doxyfile.in", "r") as file: filedata = file.read() - filedata = filedata.replace('@DOXYGEN_INPUT_DIR@', input_dir) - filedata = filedata.replace('@DOXYGEN_OUTPUT_DIR@', output_dir) + filedata = filedata.replace("@DOXYGEN_INPUT_DIR@", input_dir) + filedata = filedata.replace("@DOXYGEN_OUTPUT_DIR@", output_dir) - with open('Doxyfile', 'w') as file: + with open("Doxyfile", "w") as file: file.write(filedata) + # Check if we're running on Read the Docs' servers -read_the_docs_build = os.environ.get('READTHEDOCS', None) == 'True' +read_the_docs_build = os.environ.get("READTHEDOCS", None) == "True" # This should be a dictionary in which the keys are project names and the values # are paths to the folder containing the doxygen output for that project. breathe_projects = {} if read_the_docs_build: - input_dir = '../src' - output_dir = 'build' + input_dir = "../src" + output_dir = "build" configureDoxyfile(input_dir, output_dir) - subprocess.call('doxygen', shell=True) - breathe_projects['mp-units'] = output_dir + '/xml' + subprocess.call("doxygen", shell=True) + breathe_projects["mp-units"] = output_dir + "/xml" # This should match one of the keys in the breathe_projects dictionary and # indicates which project should be used when the project is not specified on # the directive. -breathe_default_project = 'mp-units' +breathe_default_project = "mp-units" # Allows you to specify domains for particular files according to their extension. -breathe_domain_by_extension = {"h" : "cpp"} +breathe_domain_by_extension = {"h": "cpp"} # Provides the directive flags that should be applied to all directives which # take :members:, :private-members: and :undoc-members: options. By default, # this is set to an empty list, which means no members are displayed. -breathe_default_members = ('members', ) +breathe_default_members = ("members",) diff --git a/docs/framework/units.rst b/docs/framework/units.rst index 86dd0e1b..8e37e3e2 100644 --- a/docs/framework/units.rst +++ b/docs/framework/units.rst @@ -40,38 +40,22 @@ of a `scaled_unit` class template: left to right direction package Unit <> [[../../framework/units.html]] { - abstract prefix_family [[../../framework/units.html#prefixed-unit]] - abstract no_prefix [[../../framework/units.html#named-scaled-units]] - abstract prefix [[../../framework/units.html#prefixed-unit]] - - prefix_family <|-- no_prefix - prefix_family <.. prefix - - ' prefix_family <.. named_unit - ' prefix_family <.. named_scaled_unit - ' prefix_family <.. named_derived_unit - ' prefix_family <.. alias_unit - - ' prefix <.. prefixed_unit - ' prefix <.. prefixed_alias_unit abstract scaled_unit abstract prefixed_alias_unit [[../../framework/units.html#aliased-units]] - abstract alias_unit [[../../framework/units.html#aliased-units]] - abstract named_derived_unit [[../../framework/units.html#derived-scaled-units]] - abstract derived_unit [[../../framework/units.html#derived-scaled-units]] + abstract alias_unit [[../../framework/units.html#aliased-units]] + abstract derived_scaled_unit [[../../framework/units.html#derived-scaled-units]] + abstract derived_unit [[../../framework/units.html#derived-unnamed-units]] abstract prefixed_unit [[../../framework/units.html#prefixed-unit]] - abstract named_scaled_unit [[../../framework/units.html#named-scaled-units]] - abstract named_unit [[../../framework/units.html#base-units]] - abstract unit [[../../framework/units.html#derived-unnamed-units]] + abstract named_scaled_unit [[../../framework/units.html#named-scaled-units]] + abstract named_unit [[../../framework/units.html#base-units]] - scaled_unit <|-- unit scaled_unit <|-- named_unit scaled_unit <|-- named_scaled_unit scaled_unit <|-- prefixed_unit scaled_unit <|-- derived_unit - scaled_unit <|-- named_derived_unit + scaled_unit <|-- derived_scaled_unit scaled_unit <|-- alias_unit scaled_unit <|-- prefixed_alias_unit } @@ -191,14 +175,11 @@ Those units are the scaled versions of a time dimension's base unit, namely second. Those can be defined easily in the library using `named_scaled_unit` class template:: - struct minute : named_scaled_unit {}; - struct hour : named_scaled_unit {}; - struct day : named_scaled_unit {}; + struct minute : named_scaled_unit {}; + struct hour : named_scaled_unit {}; + struct day : named_scaled_unit {}; -where `no_prefix` is a special tag type describing that the library should -not allow to define a new prefixed unit that would use this unit as a -reference ("kilohours" does not have much sense, right?). The `ratio` type -used in the definition is really similar to ``std::ratio`` but it takes +The `ratio` type used in the definition is really similar to ``std::ratio`` but it takes an additional ``Exponent`` template parameter that defines the exponent of the ratio. Another important difference is the fact that the objects of that class are used as class NTTPs rather then a type template parameter kind. @@ -227,28 +208,26 @@ complete list of all the :term:`SI` prefixes supported by the library:: namespace si { - struct prefix : prefix_family {}; - - struct yocto : units::prefix {}; - struct zepto : units::prefix {}; - struct atto : units::prefix {}; - struct femto : units::prefix {}; - struct pico : units::prefix {}; - struct nano : units::prefix {}; - struct micro : units::prefix {}; - struct milli : units::prefix {}; - struct centi : units::prefix {}; - struct deci : units::prefix {}; - struct deca : units::prefix {}; - struct hecto : units::prefix {}; - struct kilo : units::prefix {}; - struct mega : units::prefix {}; - struct giga : units::prefix {}; - struct tera : units::prefix {}; - struct peta : units::prefix {}; - struct exa : units::prefix {}; - struct zetta : units::prefix {}; - struct yotta : units::prefix {}; + struct yocto : units::prefix {}; + struct zepto : units::prefix {}; + struct atto : units::prefix {}; + struct femto : units::prefix {}; + struct pico : units::prefix {}; + struct nano : units::prefix {}; + struct micro : units::prefix {}; + struct milli : units::prefix {}; + struct centi : units::prefix {}; + struct deci : units::prefix {}; + struct deca : units::prefix {}; + struct hecto : units::prefix {}; + struct kilo : units::prefix {}; + struct mega : units::prefix {}; + struct giga : units::prefix {}; + struct tera : units::prefix {}; + struct peta : units::prefix {}; + struct exa : units::prefix {}; + struct zetta : units::prefix {}; + struct yotta : units::prefix {}; } @@ -257,14 +236,12 @@ domain:: namespace iec80000 { - struct binary_prefix : prefix_family {}; - - struct kibi : units::prefix {}; - struct mebi : units::prefix {}; - struct gibi : units::prefix {}; - struct tebi : units::prefix {}; - struct pebi : units::prefix {}; - struct exbi : units::prefix {}; + struct kibi : units::prefix {}; + struct mebi : units::prefix {}; + struct gibi : units::prefix {}; + struct tebi : units::prefix {}; + struct pebi : units::prefix {}; + struct exbi : units::prefix {}; } @@ -338,7 +315,7 @@ will result in a different unnamed unit symbol: where ``kilogram_metre_per_second`` is defined as:: - struct kilogram_metre_per_second : unit {}; + struct kilogram_metre_per_second : derived_unit {}; However, the easiest way to define momentum is just to use the ``si::dim_speed`` derived dimension in the recipe: @@ -385,12 +362,12 @@ ratio in reference to the "metre per second": Whichever, we choose there will always be someone not happy with our choice. -Thanks to a `derived_unit` class template provided by the library this problem +Thanks to a `derived_scaled_unit` class template provided by the library this problem does not exist at all. With it ``si::kilometre_per_hour`` can be defined as:: namespace si { - struct kilometre_per_hour : derived_unit {}; + struct kilometre_per_hour : derived_scaled_unit {}; } @@ -400,7 +377,7 @@ by him/her-self:: namespace si::fps { - struct knot : named_derived_unit {}; + struct knot : named_derived_unit {}; } diff --git a/docs/reference/core/concepts.rst b/docs/reference/core/concepts.rst index ecc79b8a..99f38ce9 100644 --- a/docs/reference/core/concepts.rst +++ b/docs/reference/core/concepts.rst @@ -8,10 +8,6 @@ Concepts All names defined in this chapter reside in the :any:`units` namespace unless specified otherwise. -.. concept:: template PrefixFamily - - A concept matching a prefix family. Satisfied by all types derived from :class:`prefix_family`. - .. concept:: template Prefix A concept matching a symbol prefix. Satisfied by all instantiations of :struct:`prefix`. @@ -44,6 +40,11 @@ Concepts A concept matching all unit types in the library. Satisfied by all unit types derived from the instantiation of :class:`scaled_unit`. +.. concept:: template NamedUnit + + A concept matching all unit types that have an atomic text symbol that can be used to aggregate it with + other named units to form a final symbol of a derived unit. + .. concept:: template UnitOf A concept matching only units of a specified dimension. Satisfied by all unit types that diff --git a/docs/reference/core/types/prefixes.rst b/docs/reference/core/types/prefixes.rst index 414eda66..7f160aef 100644 --- a/docs/reference/core/types/prefixes.rst +++ b/docs/reference/core/types/prefixes.rst @@ -1,11 +1,5 @@ Prefixes ======== -.. doxygenstruct:: units::prefix_family - :members: - -.. doxygenstruct:: units::no_prefix - :members: - .. doxygenstruct:: units::prefix :members: diff --git a/docs/reference/core/types/units.rst b/docs/reference/core/types/units.rst index 897fcc85..ce21fc68 100644 --- a/docs/reference/core/types/units.rst +++ b/docs/reference/core/types/units.rst @@ -4,9 +4,6 @@ Units .. doxygenstruct:: units::scaled_unit :members: -.. doxygenstruct:: units::unit - :members: - .. doxygenstruct:: units::named_unit :members: @@ -19,7 +16,7 @@ Units .. doxygenstruct:: units::derived_unit :members: -.. doxygenstruct:: units::named_derived_unit +.. doxygenstruct:: units::derived_scaled_unit :members: .. doxygenstruct:: units::alias_unit diff --git a/docs/usage.rst b/docs/usage.rst index bc289de5..bde4ea77 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -294,7 +294,7 @@ library release the following steps may be performed: mkdir my_project/build && cd my_project/build conan install .. -pr -s compiler.cppstd=20 -b=missing - cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake + cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release cmake --build . @@ -345,7 +345,7 @@ differences: mkdir my_project/build && cd my_project/build conan install .. -pr -s compiler.cppstd=20 -b=outdated -u - cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake + cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release cmake --build . @@ -360,7 +360,7 @@ to find it, it is enough to perform the following steps: mkdir units/build && cd units/build conan install .. -pr -s compiler.cppstd=20 -b=missing - cmake ../src -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake + cmake ../src -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release cmake --install . --prefix @@ -392,7 +392,7 @@ step with the CMake build: .. code-block:: shell # ... - cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake + cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release cmake --build . ctest diff --git a/docs/use_cases/extensions.rst b/docs/use_cases/extensions.rst index 9e07a92a..fd9db565 100644 --- a/docs/use_cases/extensions.rst +++ b/docs/use_cases/extensions.rst @@ -22,7 +22,7 @@ Defining a New Unit My working desk is of ``180 cm x 60 cm`` which gives an area of ``0.3 m²``. I would like to make it a unit of area for my project:: - struct desk : named_scaled_unit {}; + struct desk : named_scaled_unit {}; With the above I can define a quantity with the area of ``2 desks``:: @@ -56,28 +56,22 @@ In case I would like to check how much area ``6 desks`` take in SI units:: Enabling a Unit for Prefixing ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -In case I decide it is reasonable to express my desks with SI prefixes the only thing I have -to change in the above code is to replace `no_prefix` with `isq::si::prefix`:: - - struct desk : named_scaled_unit {}; - -Now I can define a new unit named ``kilodesk``:: +In case I decide it is reasonable to express my desks with SI prefixes, I can define +a new unit named ``kilodesk``:: struct kilodesk : prefixed_unit {}; static_assert(3_d * 1000 == si::area(3)); But maybe SI prefixes are not good for me. Maybe I always pack ``6`` desks into one package -for shipment and ``40`` such packages fit into my lorry. To express this with prefixes a new -prefix family and prefixes are needed:: +for shipment and ``40`` such packages fit into my lorry. To express this new prefix definitions +are needed:: - struct shipping_prefix : prefix_family {}; - - struct package : prefix {}; - struct lorry : prefix {}; + struct package : prefix {}; + struct lorry : prefix {}; Now we can use it for our unit:: - struct desk : named_scaled_unit {}; + struct desk : named_scaled_unit {}; struct packagedesk : prefixed_unit {}; struct lorrydesk : prefixed_unit {}; @@ -111,14 +105,14 @@ rate of wood during production I need to define a new derived dimension together coherent unit:: // coherent unit must apply to the system rules (in this case SI) - struct square_metre_per_second : unit {}; + struct square_metre_per_second : derived_unit {}; // new derived dimensions struct dim_desk_rate : derived_dimension, exponent> {}; // our unit of interest for a new derived dimension - struct desk_per_hour : derived_unit {}; + struct desk_per_hour : derived_scaled_unit {}; // a quantity of our dimension template U, Representation Rep = double> @@ -147,7 +141,7 @@ a customer's office I would need a unit called ``person_per_desk`` of a new deri dimension. However, our library does not know what a ``person`` is. For this I need to define a new base dimension, its units, quantity helper, concept, and UDLs:: - struct person : named_unit {}; + struct person : named_unit {}; struct dim_people : base_dimension<"people", person> {}; template U, Representation Rep = double> @@ -162,12 +156,12 @@ define a new base dimension, its units, quantity helper, concept, and UDLs:: With the above we can now define a new derived dimension:: - struct person_per_square_metre : unit {}; + struct person_per_square_metre : derived_unit {}; struct dim_occupancy_rate : derived_dimension, exponent> {}; - struct person_per_desk : derived_unit {}; + struct person_per_desk : derived_scaled_unit {}; template U, Representation Rep = double> using occupancy_rate = quantity; @@ -211,8 +205,8 @@ Such units do not share their references with base units of other systems: namespace fps { - struct foot : named_unit {}; - struct yard : named_scaled_unit {}; + struct foot : named_unit {}; + struct yard : named_scaled_unit {}; struct dim_length : base_dimension<"L", foot> {}; @@ -231,7 +225,7 @@ different systems: namespace si { - struct metre : named_unit {}; + struct metre : named_unit {}; struct kilometre : prefixed_unit {}; struct dim_length : base_dimension<"L", metre> {}; @@ -241,8 +235,8 @@ different systems: namespace fps { - struct foot : named_scaled_unit {}; - struct yard : named_scaled_unit {}; + struct foot : named_scaled_unit {}; + struct yard : named_scaled_unit {}; struct dim_length : base_dimension<"L", foot> {}; @@ -300,7 +294,7 @@ the library always keeps the ratio relative to the primary reference unit which in this case is ``si::metre``. This results in much bigger ratios and in case of some units may result with a problem of limited resolution of ``std::int64_t`` used to store numerator, denominator, and exponent -values of ratio. For example the ``si::fps::qubic_foot`` already has the +values of ratio. For example the ``si::fps::cubic_foot`` already has the ratio of ``ratio{55306341, 1953125, -3}``. In case of more complicated conversion ratio we can overflow `ratio` and get a compile-time error. In such a situation the standalone system may be a better choice here. diff --git a/docs/use_cases/linear_algebra.rst b/docs/use_cases/linear_algebra.rst index 6cc017b0..bb3c1111 100644 --- a/docs/use_cases/linear_algebra.rst +++ b/docs/use_cases/linear_algebra.rst @@ -11,7 +11,7 @@ enough to be used with other Linear Algebra libraries existing on the market. All of the examples provided in this chapter refer to the official proposal of the Linear Algebra Library for the C++23 defined in `P1385 `_ and its latest implementation from `GitHub `_ - or `Conan `_. + or `Conan `_. Also, to simplify the examples all of them assume:: using namespace std::math; diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 0e7a71b0..76117aa4 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -22,6 +22,9 @@ cmake_minimum_required(VERSION 3.2) +add_library(example_utils INTERFACE) +target_include_directories(example_utils INTERFACE include) + # # add_example(target ...) # diff --git a/example/aliases/foot_pound_second.cpp b/example/aliases/foot_pound_second.cpp index 588e328d..8890a92f 100644 --- a/example/aliases/foot_pound_second.cpp +++ b/example/aliases/foot_pound_second.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -68,7 +69,7 @@ void print_details(std::string_view description, const Ship& ship) << STD_FMT::format("{:20} : {}\n", "beam", fmt_line, si::length::m<>>(ship.beam)) << STD_FMT::format("{:20} : {}\n", "mass", fmt_line, si::mass::t<>>(ship.mass)) << STD_FMT::format("{:20} : {}\n", "speed", - fmt_line, si::speed::km_per_h<>>(ship.speed)) + fmt_line, si::speed::km_per_h<>>(ship.speed)) << STD_FMT::format("{:20} : {}\n", "power", fmt_line, si::power::kW<>>(ship.power)) << STD_FMT::format("{:20} : {}\n", "main guns", fmt_line, si::length::mm<>>(ship.mainGuns)) @@ -101,7 +102,7 @@ int main() auto iowa = Ship{.length{ft<>(860.)}, .draft{ft<>(37.) + in<>(2.)}, .beam{ft<>(108.) + in<>(2.)}, - .speed{knot<>(33)}, + .speed{international::kn<>(33)}, .mass{lton<>(57'540)}, .mainGuns{in<>(16)}, .shellMass{lb<>(2700)}, @@ -112,7 +113,7 @@ int main() auto kgv = Ship{.length{ft<>(745.1)}, .draft{ft<>(33.) + in<>(7.5)}, .beam{ft<>(103.2) + in<>(2.5)}, - .speed{knot<>(28.3)}, + .speed{international::kn<>(28.3)}, .mass{lton<>(42'245)}, .mainGuns{in<>(14)}, .shellMass{lb<>(1'590)}, diff --git a/example/custom_systems.cpp b/example/custom_systems.cpp index 5c8bc2a0..b2c3419d 100644 --- a/example/custom_systems.cpp +++ b/example/custom_systems.cpp @@ -32,8 +32,8 @@ using namespace units; namespace fps { -struct foot : named_unit {}; -struct yard : named_scaled_unit(), foot> {}; +struct foot : named_unit {}; +struct yard : named_scaled_unit(), foot> {}; struct dim_length : base_dimension<"L", foot> {}; @@ -44,7 +44,7 @@ using length = quantity; namespace si { -struct metre : named_unit {}; +struct metre : named_unit {}; struct kilometre : prefixed_unit {}; struct dim_length : base_dimension<"L", metre> {}; @@ -54,8 +54,8 @@ using length = quantity; namespace fps { -struct foot : named_scaled_unit(), metre> {}; -struct yard : named_scaled_unit(), foot> {}; +struct foot : named_scaled_unit(), metre> {}; +struct yard : named_scaled_unit(), foot> {}; struct dim_length : base_dimension<"L", foot> {}; diff --git a/example/glide_computer/CMakeLists.txt b/example/glide_computer/CMakeLists.txt index d98b3636..7c19f4db 100644 --- a/example/glide_computer/CMakeLists.txt +++ b/example/glide_computer/CMakeLists.txt @@ -22,6 +22,6 @@ cmake_minimum_required(VERSION 3.2) -add_library(glide_computer STATIC geographic.cpp include/geographic.h glide_computer.cpp include/glide_computer.h) -target_link_libraries(glide_computer PRIVATE mp-units::core-fmt PUBLIC mp-units::si) +add_library(glide_computer STATIC include/geographic.h glide_computer.cpp include/glide_computer.h) +target_link_libraries(glide_computer PRIVATE mp-units::core-fmt PUBLIC mp-units::si example_utils) target_include_directories(glide_computer PUBLIC include) diff --git a/example/glide_computer/geographic.cpp b/example/glide_computer/geographic.cpp deleted file mode 100644 index 4150c792..00000000 --- a/example/glide_computer/geographic.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// The MIT License (MIT) -// -// Copyright (c) 2018 Mateusz Pusz -// -// 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 "geographic.h" -#include -#include -#include - -namespace { - -using namespace units::isq::si; -inline constexpr length earth_radius(6371); - -} // namespace - -namespace geographic { - -distance spherical_distance(position from, position to) -{ - using rep = std::common_type_t; - constexpr auto p = std::numbers::pi_v / 180; - const auto lat1 = from.lat.value() * p; - const auto lon1 = from.lon.value() * p; - const auto lat2 = to.lat.value() * p; - const auto lon2 = to.lon.value() * p; - - using std::sin, std::cos, std::asin, std::sqrt; - - // https://en.wikipedia.org/wiki/Great-circle_distance#Formulae - if constexpr (sizeof(rep) >= 8) { - // spherical law of cosines - const auto central_angle = acos(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(lon2 - lon1)); - // const auto central_angle = 2 * asin(sqrt(0.5 - cos(lat2 - lat1) / 2 + cos(lat1) * cos(lat2) * (1 - cos(lon2 - - // lon1)) / 2)); - return distance(earth_radius * central_angle); - } else { - // the haversine formula - const auto sin_lat = sin((lat2 - lat1) / 2); - const auto sin_lon = sin((lon2 - lon1) / 2); - const auto central_angle = 2 * asin(sqrt(sin_lat * sin_lat + cos(lat1) * cos(lat2) * sin_lon * sin_lon)); - return distance(earth_radius * central_angle); - } -} - -} // namespace geographic diff --git a/example/glide_computer/include/geographic.h b/example/glide_computer/include/geographic.h index 44290080..851f79c6 100644 --- a/example/glide_computer/include/geographic.h +++ b/example/glide_computer/include/geographic.h @@ -22,10 +22,14 @@ #pragma once +#include "ranged_representation.h" +#include #include +#include #include #include #include +#include #include // IWYU pragma: begin_exports @@ -34,88 +38,95 @@ namespace geographic { -template -struct coordinate { - using value_type = Rep; - constexpr explicit coordinate(value_type v) : value_(v) {} - constexpr value_type value() const { return value_; } - auto operator<=>(const coordinate&) const = default; -private: - value_type value_; -}; +// TODO Change to `angle` dimension in degree unit when the work on magnitudes is done +template +using latitude = units::dimensionless>; -struct latitude : coordinate { - using coordinate::coordinate; -}; +template +using longitude = units::dimensionless>; -struct longitude : coordinate { - using coordinate::coordinate; -}; - -template -std::basic_ostream& operator<<(std::basic_ostream& os, const latitude& lat) +template +std::basic_ostream& operator<<(std::basic_ostream& os, const latitude& lat) { - if (lat.value() > 0) - return os << "N" << lat.value(); + if (lat.number() > 0) + return os << "N" << lat.number(); else - return os << "S" << -lat.value(); + return os << "S" << -lat.number(); } -template -std::basic_ostream& operator<<(std::basic_ostream& os, const longitude& lon) +template +std::basic_ostream& operator<<(std::basic_ostream& os, const longitude& lon) { - if (lon.value() > 0) - return os << "E" << lon.value(); + if (lon.number() > 0) + return os << "E" << lon.number(); else - return os << "W" << -lon.value(); + return os << "W" << -lon.number(); } inline namespace literals { -constexpr auto operator"" _N(unsigned long long v) { return latitude(static_cast(v)); } -constexpr auto operator"" _N(long double v) { return latitude(static_cast(v)); } -constexpr auto operator"" _S(unsigned long long v) { return latitude(-static_cast(v)); } -constexpr auto operator"" _S(long double v) { return latitude(-static_cast(v)); } -constexpr auto operator"" _E(unsigned long long v) { return longitude(static_cast(v)); } -constexpr auto operator"" _E(long double v) { return longitude(static_cast(v)); } -constexpr auto operator"" _W(unsigned long long v) { return longitude(-static_cast(v)); } -constexpr auto operator"" _W(long double v) { return longitude(-static_cast(v)); } +constexpr auto operator"" _N(long double v) { return latitude(latitude::rep(v)); } +constexpr auto operator"" _S(long double v) { return latitude(latitude::rep(v)); } +constexpr auto operator"" _E(long double v) { return longitude(longitude::rep(v)); } +constexpr auto operator"" _W(long double v) { return longitude(longitude::rep(v)); } +constexpr auto operator"" _N(unsigned long long v) +{ + gsl_ExpectsAudit(std::in_range(v)); + return latitude(latitude::rep(static_cast(v))); +} +constexpr auto operator"" _S(unsigned long long v) +{ + gsl_ExpectsAudit(std::in_range(v)); + return latitude(-latitude::rep(static_cast(v))); +} +constexpr auto operator"" _E(unsigned long long v) +{ + gsl_ExpectsAudit(std::in_range(v)); + return longitude(longitude::rep(static_cast(v))); +} +constexpr auto operator"" _W(unsigned long long v) +{ + gsl_ExpectsAudit(std::in_range(v)); + return longitude(-longitude::rep(static_cast(v))); +} } // namespace literals } // namespace geographic -template<> -class std::numeric_limits : public numeric_limits { - static constexpr auto min() noexcept { return geographic::latitude(-90); } - static constexpr auto lowest() noexcept { return geographic::latitude(-90); } - static constexpr auto max() noexcept { return geographic::latitude(90); } +template +class std::numeric_limits> : public numeric_limits { + static constexpr auto min() noexcept { return geographic::latitude(-90); } + static constexpr auto lowest() noexcept { return geographic::latitude(-90); } + static constexpr auto max() noexcept { return geographic::latitude(90); } }; -template<> -class std::numeric_limits : public numeric_limits { - static constexpr auto min() noexcept { return geographic::longitude(-180); } - static constexpr auto lowest() noexcept { return geographic::longitude(-180); } - static constexpr auto max() noexcept { return geographic::longitude(180); } +template +class std::numeric_limits> : public numeric_limits { + static constexpr auto min() noexcept { return geographic::longitude(-180); } + static constexpr auto lowest() noexcept { return geographic::longitude(-180); } + static constexpr auto max() noexcept { return geographic::longitude(180); } }; -template<> -struct STD_FMT::formatter : formatter { +template +struct STD_FMT::formatter> : formatter { template - auto format(geographic::latitude lat, FormatContext& ctx) + auto format(geographic::latitude lat, FormatContext& ctx) { - STD_FMT::format_to(ctx.out(), "{}", lat.value() > 0 ? 'N' : 'S'); - return formatter::format(lat.value() > 0 ? lat.value() : -lat.value(), ctx); + using rep = TYPENAME geographic::latitude::rep; + STD_FMT::format_to(ctx.out(), "{}", lat > rep{0} ? 'N' : 'S'); + return formatter::format(lat > rep{0} ? lat.number() : -lat.number(), ctx); } }; -template<> -struct STD_FMT::formatter : formatter { +template +struct STD_FMT::formatter> : formatter { template - auto format(geographic::longitude lon, FormatContext& ctx) + auto format(geographic::longitude lon, FormatContext& ctx) { - STD_FMT::format_to(ctx.out(), "{}", lon.value() > 0 ? 'E' : 'W'); - return formatter::format(lon.value() > 0 ? lon.value() : -lon.value(), ctx); + using rep = TYPENAME geographic::longitude::rep; + STD_FMT::format_to(ctx.out(), "{}", lon > rep{0} ? 'E' : 'W'); + return formatter::format(lon > rep{0} ? lon.number() : -lon.number(), ctx); } }; @@ -124,11 +135,41 @@ namespace geographic { struct horizontal_kind : units::kind {}; using distance = units::quantity_kind; +template struct position { - latitude lat; - longitude lon; + latitude lat; + longitude lon; }; -distance spherical_distance(position from, position to); +template +distance spherical_distance(position from, position to) +{ + using namespace units::isq::si; + constexpr length earth_radius(6371); + + constexpr auto p = std::numbers::pi_v / 180; + const auto lat1_rad = from.lat.number() * p; + const auto lon1_rad = from.lon.number() * p; + const auto lat2_rad = to.lat.number() * p; + const auto lon2_rad = to.lon.number() * p; + + using std::sin, std::cos, std::asin, std::acos, std::sqrt; + + // https://en.wikipedia.org/wiki/Great-circle_distance#Formulae + if constexpr (sizeof(T) >= 8) { + // spherical law of cosines + const auto central_angle = + acos(sin(lat1_rad) * sin(lat2_rad) + cos(lat1_rad) * cos(lat2_rad) * cos(lon2_rad - lon1_rad)); + // const auto central_angle = 2 * asin(sqrt(0.5 - cos(lat2_rad - lat1_rad) / 2 + cos(lat1_rad) * cos(lat2_rad) * (1 + // - cos(lon2_rad - lon1_rad)) / 2)); + return distance(earth_radius * central_angle); + } else { + // the haversine formula + const auto sin_lat = sin((lat2_rad - lat1_rad) / 2); + const auto sin_lon = sin((lon2_rad - lon1_rad) / 2); + const auto central_angle = 2 * asin(sqrt(sin_lat * sin_lat + cos(lat1_rad) * cos(lat2_rad) * sin_lon * sin_lon)); + return distance(earth_radius * central_angle); + } +} } // namespace geographic diff --git a/example/glide_computer/include/glide_computer.h b/example/glide_computer/include/glide_computer.h index d545ea7a..c515868c 100644 --- a/example/glide_computer/include/glide_computer.h +++ b/example/glide_computer/include/glide_computer.h @@ -136,7 +136,7 @@ struct weather { struct waypoint { std::string name; - geographic::position pos; + geographic::position pos; altitude alt; }; diff --git a/example/include/ranged_representation.h b/example/include/ranged_representation.h new file mode 100644 index 00000000..3d7b2a88 --- /dev/null +++ b/example/include/ranged_representation.h @@ -0,0 +1,51 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// 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. + +#pragma once + +#include "validated_type.h" +#include +#include +#include + +template +inline constexpr auto is_in_range = [](const auto& v) { return std::clamp(v, T{Min}, T{Max}) == v; }; + +template +using is_in_range_t = decltype(is_in_range); + +template +class ranged_representation : public validated_type> { +public: + using validated_type>::validated_type; + constexpr ranged_representation() : validated_type>(T{}) {} + + [[nodiscard]] constexpr ranged_representation operator-() const { return ranged_representation(-this->value()); } +}; + +template +struct std::common_type> : + std::type_identity, Min, Max>> {}; + +template +struct std::common_type, std::intmax_t> : + std::type_identity, Min, Max>> {}; diff --git a/example/include/validated_type.h b/example/include/validated_type.h new file mode 100644 index 00000000..bf44bbbc --- /dev/null +++ b/example/include/validated_type.h @@ -0,0 +1,81 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// 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. + +#pragma once + +#include +#include +#include + +inline constexpr struct validated_tag { +} validated; + +template Validator> +class validated_type { + T value_; +public: + using value_type = T; + + static constexpr bool validate(const T& value) { return Validator()(value); } + + constexpr explicit validated_type(const T& value) noexcept(std::is_nothrow_copy_constructible_v) + requires std::copyable + : value_(value) + { + gsl_Expects(validate(value_)); + } + + constexpr explicit validated_type(T&& value) noexcept(std::is_nothrow_move_constructible_v) : + value_(std::move(value)) + { + gsl_Expects(validate(value_)); + } + + constexpr validated_type(const T& value, validated_tag) noexcept(std::is_nothrow_copy_constructible_v) + requires std::copyable + : value_(value) + { + } + + constexpr validated_type(T&& value, validated_tag) noexcept(std::is_nothrow_move_constructible_v) : + value_(std::move(value)) + { + } + + constexpr explicit(false) operator T() const noexcept(std::is_nothrow_copy_constructible_v) + requires std::copyable + { + return value_; + } + + constexpr T& value() & noexcept = delete; + constexpr const T& value() const& noexcept { return value_; } + constexpr T&& value() && noexcept { return std::move(value_); } + constexpr const T&& value() const&& noexcept { return std::move(value_); } + + bool operator==(const validated_type&) const + requires std::equality_comparable + = default; + auto operator<=>(const validated_type&) const + requires std::three_way_comparable + = default; +}; diff --git a/example/kalman_filter/kalman.h b/example/kalman_filter/kalman.h index 16a21375..a034d2db 100644 --- a/example/kalman_filter/kalman.h +++ b/example/kalman_filter/kalman.h @@ -84,7 +84,7 @@ public: uncertainty_type uncertainty; }; -#if UNITS_COMP_CLANG <= 13 +#if UNITS_COMP_CLANG <= 14 template estimation(state, U) -> estimation; diff --git a/example/kalman_filter/kalman_filter-example_6.cpp b/example/kalman_filter/kalman_filter-example_6.cpp index fac8c34b..b77d3d62 100644 --- a/example/kalman_filter/kalman_filter-example_6.cpp +++ b/example/kalman_filter/kalman_filter-example_6.cpp @@ -32,7 +32,7 @@ // TODO Fix when Celsius is properly supported (#232) namespace units::isq::si { -struct degree_celsius : alias_unit {}; +struct degree_celsius : alias_unit {}; namespace thermodynamic_temperature_references { diff --git a/example/kalman_filter/kalman_filter-example_7.cpp b/example/kalman_filter/kalman_filter-example_7.cpp index 42ce7025..7387ab56 100644 --- a/example/kalman_filter/kalman_filter-example_7.cpp +++ b/example/kalman_filter/kalman_filter-example_7.cpp @@ -32,7 +32,7 @@ // TODO Fix when Celsius is properly supported (#232) namespace units::isq::si { -struct degree_celsius : alias_unit {}; +struct degree_celsius : alias_unit {}; namespace thermodynamic_temperature_references { diff --git a/example/kalman_filter/kalman_filter-example_8.cpp b/example/kalman_filter/kalman_filter-example_8.cpp index 3b81ae70..c2e0e1f6 100644 --- a/example/kalman_filter/kalman_filter-example_8.cpp +++ b/example/kalman_filter/kalman_filter-example_8.cpp @@ -32,7 +32,7 @@ // TODO Fix when Celsius is properly supported (#232) namespace units::isq::si { -struct degree_celsius : alias_unit {}; +struct degree_celsius : alias_unit {}; namespace thermodynamic_temperature_references { diff --git a/example/literals/custom_systems.cpp b/example/literals/custom_systems.cpp deleted file mode 100644 index ef683b98..00000000 --- a/example/literals/custom_systems.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// The MIT License (MIT) -// -// Copyright (c) 2018 Mateusz Pusz -// -// 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 - -using namespace units; - -namespace fps { - -struct foot : named_unit {}; -struct yard : named_scaled_unit(), foot> {}; - -struct dim_length : base_dimension<"L", foot> {}; - -template U, Representation Rep = double> -using length = quantity; - -} // namespace fps - -namespace si { - -struct metre : named_unit {}; -struct kilometre : prefixed_unit {}; - -struct dim_length : base_dimension<"L", metre> {}; - -template U, Representation Rep = double> -using length = quantity; - -namespace fps { - -struct foot : named_scaled_unit(), metre> {}; -struct yard : named_scaled_unit(), foot> {}; - -struct dim_length : base_dimension<"L", foot> {}; - -template U, Representation Rep = double> -using length = quantity; - -} // namespace fps -} // namespace si - -void conversions() -{ - // constexpr auto fps_yard = fps::length(1.); - // std::cout << quantity_cast(fps_yard) << "\n"; - - constexpr auto si_fps_yard = si::fps::length(1.); - std::cout << quantity_cast(si_fps_yard) << "\n"; -} - -void unknown_dimensions() -{ - constexpr auto fps_yard = fps::length(1.); - constexpr auto fps_area = quantity_cast(fps_yard * fps_yard); - std::cout << fps_yard << "\n"; - std::cout << fps_area << "\n"; - - constexpr auto si_fps_yard = si::fps::length(1.); - constexpr auto si_fps_area = quantity_cast(si_fps_yard * si_fps_yard); - std::cout << si_fps_yard << "\n"; - std::cout << si_fps_area << "\n"; -} - -std::ostream& operator<<(std::ostream& os, const ratio& r) -{ - return os << "ratio{" << r.num << ", " << r.den << ", " << r.exp << "}"; -} - -template -std::ostream& operator<<(std::ostream& os, const U& u) -{ - using unit_type = std::remove_cvref_t; - return os << as_ratio(unit_type::mag) << " x " << unit_type::reference::symbol.standard(); -} - -void what_is_your_ratio() -{ - std::cout << "fps: " << fps::yard() << "\n"; - std::cout << "si::fps: " << si::fps::yard() << "\n"; -} - -int main() -{ - conversions(); - unknown_dimensions(); - what_is_your_ratio(); -} diff --git a/example/literals/foot_pound_second.cpp b/example/literals/foot_pound_second.cpp index 69df4f51..01f8d285 100644 --- a/example/literals/foot_pound_second.cpp +++ b/example/literals/foot_pound_second.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -73,8 +74,9 @@ void print_details(std::string_view description, const Ship& ship) fmt_line, si::length>(ship.beam)) << STD_FMT::format("{:20} : {}\n", "mass", fmt_line, si::mass>(ship.mass)) - << STD_FMT::format("{:20} : {}\n", "speed", - fmt_line, si::speed>(ship.speed)) + << STD_FMT::format( + "{:20} : {}\n", "speed", + fmt_line, si::speed>(ship.speed)) << STD_FMT::format("{:20} : {}\n", "power", fmt_line, si::power>(ship.power)) << STD_FMT::format("{:20} : {}\n", "main guns", @@ -108,7 +110,7 @@ int main() auto iowa = Ship{.length{860._q_ft}, .draft{37._q_ft + 2._q_in}, .beam{108._q_ft + 2._q_in}, - .speed{33_q_knot}, + .speed{si::speed{33}}, .mass{57'540_q_lton}, .mainGuns{16_q_in}, .shellMass{2700_q_lb}, @@ -119,7 +121,7 @@ int main() auto kgv = Ship{.length{745.1_q_ft}, .draft{33._q_ft + 7.5_q_in}, .beam{103.2_q_ft + 2.5_q_in}, - .speed{28.3_q_knot}, + .speed{si::speed{28.3}}, .mass{42'245_q_lton}, .mainGuns{14_q_in}, .shellMass{1'590_q_lb}, diff --git a/example/references/foot_pound_second.cpp b/example/references/foot_pound_second.cpp index f947ed4c..0833fa6b 100644 --- a/example/references/foot_pound_second.cpp +++ b/example/references/foot_pound_second.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -76,8 +77,9 @@ void print_details(std::string_view description, const Ship& ship) fmt_line, si::length>(ship.beam)) << STD_FMT::format("{:20} : {}\n", "mass", fmt_line, si::mass>(ship.mass)) - << STD_FMT::format("{:20} : {}\n", "speed", - fmt_line, si::speed>(ship.speed)) + << STD_FMT::format( + "{:20} : {}\n", "speed", + fmt_line, si::speed>(ship.speed)) << STD_FMT::format("{:20} : {}\n", "power", fmt_line, si::power>(ship.power)) << STD_FMT::format("{:20} : {}\n", "main guns", @@ -112,7 +114,7 @@ int main() auto iowa = Ship{.length{860. * ft}, .draft{37. * ft + 2. * in}, .beam{108. * ft + 2. * in}, - .speed{33 * knot}, + .speed{33 * units::isq::si::international::references::kn}, .mass{57'540 * lton}, .mainGuns{16 * in}, .shellMass{2700 * lb}, @@ -123,7 +125,7 @@ int main() auto kgv = Ship{.length{745.1 * ft}, .draft{33. * ft + 7.5 * in}, .beam{103.2 * ft + 2.5 * in}, - .speed{28.3 * knot}, + .speed{28.3 * units::isq::si::international::references::kn}, .mass{42'245 * lton}, .mainGuns{14 * in}, .shellMass{1'590 * lb}, diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4ed41451..32a5e555 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,7 +20,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) project(mp-units VERSION 0.8.0 LANGUAGES CXX) set(projectPrefix UNITS_) diff --git a/src/cmake/AddUnitsModule.cmake b/src/cmake/AddUnitsModule.cmake index bac9a57d..7e52697b 100644 --- a/src/cmake/AddUnitsModule.cmake +++ b/src/cmake/AddUnitsModule.cmake @@ -20,14 +20,43 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) + +function(validate_unparsed module prefix) + if(${prefix}_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Invalid arguments '${${prefix}_UNPARSED_ARGUMENTS}' " "for module '${module}'") + endif() +endfunction() + +function(validate_argument_exists module prefix arg) + if(NOT ${prefix}_${arg}) + message(FATAL_ERROR "'${arg}' not provided for module '${module}'") + endif() +endfunction() + +function(validate_arguments_exists module prefix) + foreach(arg ${ARGN}) + validate_argument_exists(${module} ${prefix} ${arg}) + endforeach() +endfunction() # -# add_units_module(ModuleName ...) +# add_units_module(ModuleName +# DEPENDENCIES ... +# HEADERS ...) # function(add_units_module name) - add_library(mp-units-${name} INTERFACE) - target_link_libraries(mp-units-${name} INTERFACE ${ARGN}) + # parse arguments + set(multiValues DEPENDENCIES HEADERS) + cmake_parse_arguments(PARSE_ARGV 1 ARG "" "" "${multiValues}") + + # validate and process arguments + validate_unparsed(${name} ARG) + validate_arguments_exists(${name} ARG DEPENDENCIES HEADERS) + + # define the target for a module + add_library(mp-units-${name} INTERFACE ${ARG_HEADERS}) + target_link_libraries(mp-units-${name} INTERFACE ${ARG_DEPENDENCIES}) target_include_directories( mp-units-${name} ${unitsAsSystem} INTERFACE $ $ diff --git a/src/core-fmt/CMakeLists.txt b/src/core-fmt/CMakeLists.txt index 1ee5e6f7..d88d23f4 100644 --- a/src/core-fmt/CMakeLists.txt +++ b/src/core-fmt/CMakeLists.txt @@ -20,12 +20,12 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) option(${projectPrefix}USE_LIBFMT "Enables usage of libfmt instead of the one from 'std'" ON) message(STATUS "${projectPrefix}USE_LIBFMT: ${${projectPrefix}USE_LIBFMT}") -add_units_module(core-fmt mp-units::core) +add_units_module(core-fmt DEPENDENCIES mp-units::core HEADERS include/units/format.h) target_compile_definitions(mp-units-core-fmt INTERFACE ${projectPrefix}USE_LIBFMT=$) if(${projectPrefix}USE_LIBFMT) diff --git a/src/core-io/CMakeLists.txt b/src/core-io/CMakeLists.txt index dc34d127..de797acf 100644 --- a/src/core-io/CMakeLists.txt +++ b/src/core-io/CMakeLists.txt @@ -20,6 +20,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) -add_units_module(core-io mp-units::core) +add_units_module(core-io DEPENDENCIES mp-units::core HEADERS include/units/quantity_io.h) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 4a4682be..431f258a 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -20,7 +20,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) # core library options set(${projectPrefix}DOWNCAST_MODE ON CACHE STRING "Select downcasting mode") @@ -34,7 +34,33 @@ include(CheckLibcxxInUse) check_libcxx_in_use(${projectPrefix}LIBCXX) # core library definition -add_library(mp-units-core INTERFACE) +add_library( + mp-units-core + INTERFACE + include/units/base_dimension.h + include/units/chrono.h + include/units/concepts.h + include/units/customization_points.h + include/units/derived_dimension.h + include/units/exponent.h + include/units/generic/angle.h + include/units/generic/dimensionless.h + include/units/kind.h + include/units/magnitude.h + include/units/math.h + include/units/point_origin.h + include/units/prefix.h + include/units/quantity.h + include/units/quantity_cast.h + include/units/quantity_kind.h + include/units/quantity_point.h + include/units/quantity_point_kind.h + include/units/random.h + include/units/ratio.h + include/units/reference.h + include/units/symbol_text.h + include/units/unit.h +) target_compile_features(mp-units-core INTERFACE cxx_std_20) target_link_libraries(mp-units-core INTERFACE gsl::gsl-lite) target_include_directories( diff --git a/src/core/include/units/base_dimension.h b/src/core/include/units/base_dimension.h index 14421e25..7515d97b 100644 --- a/src/core/include/units/base_dimension.h +++ b/src/core/include/units/base_dimension.h @@ -50,8 +50,7 @@ namespace units { * @tparam Symbol an unique identifier of the base dimension used to provide dimensional analysis support * @tparam U a base unit to be used for this base dimension */ -template - requires U::is_named +template struct base_dimension { static constexpr auto symbol = Symbol; ///< Unique base dimension identifier using base_unit = U; ///< Base unit adopted for this dimension diff --git a/src/core/include/units/bits/basic_concepts.h b/src/core/include/units/bits/basic_concepts.h index 54f328aa..dfe207f7 100644 --- a/src/core/include/units/bits/basic_concepts.h +++ b/src/core/include/units/bits/basic_concepts.h @@ -37,25 +37,14 @@ namespace units { -// PrefixFamily -struct prefix_family; - -/** - * @brief A concept matching a prefix family - * - * Satisfied by all types derived from `prefix_family` - */ -template -concept PrefixFamily = std::derived_from; - // Prefix namespace detail { -template +template struct prefix_base; -template -void to_prefix_base(const volatile prefix_base*); +template +void to_prefix_base(const volatile prefix_base*); } // namespace detail @@ -87,9 +76,18 @@ void to_base_scaled_unit(const volatile scaled_unit*); template concept Unit = requires(T* t) { detail::to_base_scaled_unit(t); }; +namespace detail { + +template +inline constexpr bool is_named = false; + +} + +template +concept NamedUnit = Unit && detail::is_named; + // BaseDimension -template - requires U::is_named +template struct base_dimension; namespace detail { diff --git a/src/core/include/units/bits/derived_unit.h b/src/core/include/units/bits/derived_scaled_unit.h similarity index 92% rename from src/core/include/units/bits/derived_unit.h rename to src/core/include/units/bits/derived_scaled_unit.h index 61a83986..60e9e506 100644 --- a/src/core/include/units/bits/derived_unit.h +++ b/src/core/include/units/bits/derived_scaled_unit.h @@ -34,7 +34,7 @@ inline constexpr bool same_scaled_units = false; template inline constexpr bool same_scaled_units, Us...> = (UnitOf && ...); -// derived_unit +// derived_scaled_unit template constexpr Magnitude auto derived_mag(exponent_list) @@ -44,6 +44,6 @@ constexpr Magnitude auto derived_mag(exponent_list) } template -using derived_unit = scaled_unit(typename D::recipe()), typename D::coherent_unit::reference>; +using derived_scaled_unit = scaled_unit(typename D::recipe()), typename D::coherent_unit::reference>; } // namespace units::detail diff --git a/src/core/include/units/bits/unit_text.h b/src/core/include/units/bits/unit_text.h index 09193f70..45345468 100644 --- a/src/core/include/units/bits/unit_text.h +++ b/src/core/include/units/bits/unit_text.h @@ -26,6 +26,7 @@ #include #include #include +#include namespace units::detail { @@ -57,28 +58,19 @@ constexpr auto ratio_text() } } -template +template constexpr auto prefix_or_ratio_text() { if constexpr (R.num == 1 && R.den == 1 && R.exp == 0) { // no ratio/prefix return basic_fixed_string(""); } else { - if constexpr (!is_same_v) { - // try to form a prefix - using prefix = downcast>; + // try to form a prefix + using prefix = downcast>; - if constexpr (!is_same_v>) { - // print as a prefixed unit - return prefix::symbol; - } else { - // print as a ratio of the coherent unit - constexpr auto txt = ratio_text(); - if constexpr (SymbolLen > 0 && txt.standard().size() > 0) - return txt + basic_fixed_string(" "); - else - return txt; - } + if constexpr (can_be_prefixed && !is_same_v>) { + // print as a prefixed unit + return prefix::symbol; } else { // print as a ratio of the coherent unit constexpr auto txt = ratio_text(); @@ -110,7 +102,7 @@ template constexpr auto exponent_list_with_named_units(Exp) { using dim = TYPENAME Exp::dimension; - if constexpr (dimension_unit::is_named) { + if constexpr (NamedUnit>) { return exponent_list(); } else { using recipe = TYPENAME dim::recipe; @@ -147,21 +139,16 @@ constexpr auto unit_text() // print as a prefix or ratio of a coherent unit using coherent_unit = dimension_unit; - if constexpr (has_symbol) { - // use predefined coherent unit symbol - constexpr auto symbol_text = coherent_unit::symbol; - constexpr auto prefix_txt = - prefix_or_ratio_text(); - return prefix_txt + symbol_text; - } else { - // use derived dimension ingredients to create a unit symbol - constexpr auto symbol_text = derived_dimension_unit_text(); - constexpr auto prefix_txt = - prefix_or_ratio_text(); - return prefix_txt + symbol_text; - } + constexpr auto symbol_text = []() { + if constexpr (has_symbol) + return coherent_unit::symbol; + else + return derived_dimension_unit_text(); + }(); + + constexpr auto prefix_txt = + prefix_or_ratio_text(); + return prefix_txt + symbol_text; } } diff --git a/src/core/include/units/generic/angle.h b/src/core/include/units/generic/angle.h index 9aefafbb..11017a68 100644 --- a/src/core/include/units/generic/angle.h +++ b/src/core/include/units/generic/angle.h @@ -32,7 +32,7 @@ namespace units { -struct radian : named_unit {}; +struct radian : named_unit {}; template struct dim_angle : base_dimension<"A", U> {}; diff --git a/src/core/include/units/generic/dimensionless.h b/src/core/include/units/generic/dimensionless.h index ee96af8e..fc7b97e6 100644 --- a/src/core/include/units/generic/dimensionless.h +++ b/src/core/include/units/generic/dimensionless.h @@ -30,8 +30,8 @@ namespace units { -struct one : named_unit {}; -struct percent : named_scaled_unit(), one> {}; +struct one : derived_unit {}; +struct percent : named_scaled_unit(), one> {}; /** * @brief Dimension one diff --git a/src/core/include/units/prefix.h b/src/core/include/units/prefix.h index 83adcb99..e460b4de 100644 --- a/src/core/include/units/prefix.h +++ b/src/core/include/units/prefix.h @@ -32,26 +32,10 @@ namespace units { -/** - * @brief The base for all prefix families - * - * Every prefix family should inherit from this type to satisfy PrefixFamily concept. - */ -struct prefix_family {}; - -/** - * @brief No prefix possible for the unit - * - * This is a special prefix type tag specifying that the unit can not be scaled with any kind - * of the prefix. - */ -struct no_prefix : prefix_family {}; - namespace detail { -template -struct prefix_base : downcast_base> { - using prefix_family = PF; +template +struct prefix_base : downcast_base> { static constexpr Magnitude auto mag = as_magnitude(); }; @@ -64,17 +48,14 @@ struct prefix_base : downcast_base> { * - when defining a prefixed_unit its ratio is used to scale the reference unit and its * symbol is used to prepend to the symbol of referenced unit * - when printing the symbol of a scaled unit that was not predefined by the user but its - * factor matches ratio of a prefix from the specified prefix family, its symbol will be - * prepended to the symbol of the unit + * factor matches ratio of a prefix, its symbol will be prepended to the symbol of the unit * * @tparam Child inherited class type used by the downcasting facility (CRTP Idiom) - * @tparam PF a type of prefix family * @tparam Symbol a text representation of the prefix * @tparam R factor to be used to scale a unit */ -template - requires(!std::same_as) -struct prefix : downcast_dispatch, downcast_mode::on> { +template +struct prefix : downcast_dispatch, downcast_mode::on> { static constexpr auto symbol = Symbol; }; diff --git a/src/core/include/units/quantity.h b/src/core/include/units/quantity.h index de2741d8..8b286259 100644 --- a/src/core/include/units/quantity.h +++ b/src/core/include/units/quantity.h @@ -45,6 +45,12 @@ inline constexpr auto make_quantity = [](auto&& v) { return quantity(std::forward(v)); }; +template +concept quantity_one = + Quantity && + (std::same_as || std::same_as>) && + detail::equivalent_unit::value; + } // namespace detail template @@ -133,8 +139,7 @@ public: template requires(safe_convertible_to_, rep>) - constexpr explicit(!(std::same_as && std::same_as)) quantity(Value&& v) : - number_(std::forward(v)) + constexpr explicit(!detail::quantity_one) quantity(Value&& v) : number_(std::forward(v)) { } @@ -252,9 +257,9 @@ public: number_ *= rhs; return *this; } - template - constexpr quantity& operator*=(const dimensionless& rhs) - requires requires(rep a, const Rep2 b) { + template + constexpr quantity& operator*=(const Q& rhs) + requires requires(rep a, const typename Q::rep b) { { a *= b } -> std::same_as; @@ -276,15 +281,15 @@ public: number_ /= rhs; return *this; } - template - constexpr quantity& operator/=(const dimensionless& rhs) - requires requires(rep a, const Rep2 b) { + template + constexpr quantity& operator/=(const Q& rhs) + requires requires(rep a, const typename Q::rep b) { { a /= b } -> std::same_as; } { - gsl_ExpectsAudit(rhs.number() != quantity_values::zero()); + gsl_ExpectsAudit(rhs.number() != quantity_values::zero()); number_ /= rhs.number(); return *this; } @@ -302,15 +307,15 @@ public: return *this; } - template - constexpr quantity& operator%=(const dimensionless& rhs) - requires(!floating_point_) && (!floating_point_) && requires(rep a, const Rep2 b) { - { - a %= b - } -> std::same_as; - } + template + constexpr quantity& operator%=(const Q& rhs) + requires(!floating_point_) && (!floating_point_) && requires(rep a, const typename Q::rep b) { + { + a %= b + } -> std::same_as; + } { - gsl_ExpectsAudit(rhs.number() != quantity_values::zero()); + gsl_ExpectsAudit(rhs.number() != quantity_values::zero()); number_ %= rhs.number(); return *this; } diff --git a/src/core/include/units/quantity_kind.h b/src/core/include/units/quantity_kind.h index a4bcc594..a47fd547 100644 --- a/src/core/include/units/quantity_kind.h +++ b/src/core/include/units/quantity_kind.h @@ -54,6 +54,10 @@ inline constexpr auto downcasted_kind_fn = [](auto q) { template inline constexpr auto& downcasted_kind = downcasted_kind_fn; +template +concept quantity_kind_one = QuantityKind && equivalent> && + detail::quantity_one; + } // namespace detail /** @@ -198,8 +202,8 @@ public: q_ *= rhs; return *this; } - template - constexpr quantity_kind& operator*=(const quantity_kind, units::one, Rep2>& rhs) + template QK> + constexpr quantity_kind& operator*=(const QK& rhs) requires requires(quantity_type q) { q *= rhs.common(); } { q_ *= rhs.common(); @@ -214,8 +218,8 @@ public: q_ /= rhs; return *this; } - template - constexpr quantity_kind& operator/=(const quantity_kind, units::one, Rep2>& rhs) + template QK> + constexpr quantity_kind& operator/=(const QK& rhs) requires requires(quantity_type q) { q /= rhs.common(); } { q_ /= rhs.common(); @@ -233,8 +237,7 @@ public: template constexpr quantity_kind& operator%=(const QK& rhs) - requires(QuantityKindEquivalentTo || - std::same_as>) && + requires(QuantityKindEquivalentTo || detail::quantity_kind_one) && requires(quantity_type q) { q %= rhs.common(); } { gsl_ExpectsAudit(rhs.common().number() != quantity_values::zero()); diff --git a/src/core/include/units/symbol_text.h b/src/core/include/units/symbol_text.h index 3af267a0..adf138e5 100644 --- a/src/core/include/units/symbol_text.h +++ b/src/core/include/units/symbol_text.h @@ -78,16 +78,16 @@ struct basic_symbol_text { { detail::validate_ascii_string(std.data_); } - constexpr basic_symbol_text(const StandardCharT (&std)[N + 1], const char (&a)[M + 1]) noexcept : - standard_(std), ascii_(a) + constexpr basic_symbol_text(const StandardCharT (&std)[N + 1], const char (&ascii)[M + 1]) noexcept : + standard_(std), ascii_(ascii) { - detail::validate_ascii_string(a); + detail::validate_ascii_string(ascii); } constexpr basic_symbol_text(const basic_fixed_string& std, - const basic_fixed_string& a) noexcept : - standard_(std), ascii_(a) + const basic_fixed_string& ascii) noexcept : + standard_(std), ascii_(ascii) { - detail::validate_ascii_string(a.data_); + detail::validate_ascii_string(ascii.data_); } [[nodiscard]] constexpr auto& standard() { return standard_; } diff --git a/src/core/include/units/unit.h b/src/core/include/units/unit.h index efae76ba..f5d14220 100644 --- a/src/core/include/units/unit.h +++ b/src/core/include/units/unit.h @@ -26,7 +26,7 @@ #include // IWYU pragma: begin_exports -#include +#include #include #include #include @@ -36,6 +36,13 @@ namespace units { +namespace detail { + +template +inline constexpr bool can_be_prefixed = false; + +} // namespace detail + /** * @brief A common point for a hierarchy of units * @@ -63,58 +70,34 @@ using downcast_unit = downcast::refere template struct same_unit_reference : is_same {}; -/** - * @brief An unnamed unit - * - * Defines a new unnamed (in most cases coherent) derived unit of a specific derived dimension - * and it should be passed in this dimension's definition. - * - * @tparam Child inherited class type used by the downcasting facility (CRTP Idiom) - */ -template -struct unit : downcast_dispatch(), Child>> { - static constexpr bool is_named = false; - using prefix_family = no_prefix; -}; - /** * @brief A named unit * * Defines a named (in most cases coherent) unit that is then passed to a dimension definition. - * A named unit may be used by other units defined with the prefix of the same type, unless - * no_prefix is provided for PF template parameter (in such a case it is impossible to define - * a prefix unit based on this one). + * A named unit may be composed with a prefix to create a prefixed_unit. * * @tparam Child inherited class type used by the downcasting facility (CRTP Idiom) * @tparam Symbol a short text representation of the unit - * @tparam PF no_prefix or a type of prefix family */ -template +template struct named_unit : downcast_dispatch(), Child>> { - static constexpr bool is_named = true; static constexpr auto symbol = Symbol; - using prefix_family = PF; }; /** - * @brief A scaled unit + * @brief A named scaled unit * - * Defines a new named unit that is a scaled version of another unit. Such unit can be used by - * other units defined with the prefix of the same type, unless no_prefix is provided for PF - * template parameter (in such a case it is impossible to define a prefix unit based on this - * one). + * Defines a new named unit that is a scaled version of another unit. + * A named unit may be composed with a prefix to create a prefixed_unit. * * @tparam Child inherited class type used by the downcasting facility (CRTP Idiom) * @tparam Symbol a short text representation of the unit - * @tparam PF no_prefix or a type of prefix family * @tparam M the Magnitude by which to scale U * @tparam U a reference unit to scale */ -template +template struct named_scaled_unit : downcast_dispatch> { - static constexpr bool is_named = true; static constexpr auto symbol = Symbol; - using prefix_family = PF; }; /** @@ -128,14 +111,23 @@ struct named_scaled_unit : downcast_dispatch - requires U::is_named && std::same_as +template + requires detail::can_be_prefixed struct prefixed_unit : downcast_dispatch> { - static constexpr bool is_named = true; static constexpr auto symbol = P::symbol + U::symbol; - using prefix_family = no_prefix; }; +/** + * @brief A coherent unit of a derived quantity + * + * Defines a new coherent unit of a derived quantity. It should be passed as a coherent unit + * in the dimension's definition for such a quantity. + * + * @tparam Child inherited class type used by the downcasting facility (CRTP Idiom) + */ +template +struct derived_unit : downcast_dispatch> {}; + /** * @brief A unit with a deduced ratio and symbol * @@ -149,36 +141,10 @@ struct prefixed_unit : downcast_dispatch - requires detail::same_scaled_units && - (U::is_named && (URest::is_named && ... && true)) -struct derived_unit : downcast_dispatch> { - static constexpr bool is_named = false; - static constexpr auto symbol = detail::derived_symbol_text(); - using prefix_family = no_prefix; -}; - -/** - * @brief A named unit with a deduced ratio - * - * Defines a new unit with a deduced ratio and the given symbol based on the recipe from the provided - * derived dimension. The number and order of provided units should match the recipe of the - * derived dimension. All of the units provided should also be a named ones so it is possible - * to create a deduced symbol text. - * - * @tparam Child inherited class type used by the downcasting facility (CRTP Idiom) - * @tparam Dim a derived dimension recipe to use for deduction - * @tparam Symbol a short text representation of the unit - * @tparam PF no_prefix or a type of prefix family - * @tparam U the unit of the first composite dimension from provided derived dimension's recipe - * @tparam URest the units for the rest of dimensions from the recipe - */ -template +template requires detail::same_scaled_units -struct named_derived_unit : downcast_dispatch> { - static constexpr bool is_named = true; - static constexpr auto symbol = Symbol; - using prefix_family = PF; +struct derived_scaled_unit : downcast_dispatch> { + static constexpr auto symbol = detail::derived_symbol_text(); }; /** @@ -186,19 +152,14 @@ struct named_derived_unit : downcast_dispatch +template struct alias_unit : U { - static constexpr bool is_named = true; static constexpr auto symbol = Symbol; - using prefix_family = PF; }; /** @@ -215,20 +176,55 @@ struct alias_unit : U { // TODO gcc bug: 95015 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95015 // template -// requires (!AliasUnit) && std::same_as -template - requires AU::is_named && std::same_as +// requires (!AliasUnit) +template + requires detail::can_be_prefixed struct prefixed_alias_unit : U { - static constexpr bool is_named = true; static constexpr auto symbol = P::symbol + AU::symbol; - using prefix_family = no_prefix; }; /** - * @brief Unknown unit + * @brief Unknown coherent unit * * Used as a coherent unit of an unknown dimension. */ -struct unknown_coherent_unit : unit {}; +struct unknown_coherent_unit : derived_unit {}; + +namespace detail { + +template +void is_named_impl(const volatile named_unit*); + +template +void is_named_impl(const volatile named_scaled_unit*); + +template +void is_named_impl(const volatile prefixed_unit*); + +template +void is_named_impl(const volatile alias_unit*); + +template +void is_named_impl(const volatile prefixed_alias_unit*); + +template +inline constexpr bool is_named = requires(U * u) { is_named_impl(u); }; + +template +void can_be_prefixed_impl(const volatile named_unit*); + +template +void can_be_prefixed_impl(const volatile named_scaled_unit*); + +template +void can_be_prefixed_impl(const volatile alias_unit*); + +template +inline constexpr bool can_be_prefixed = requires(U * u) { can_be_prefixed_impl(u); }; + +template +inline constexpr bool can_be_prefixed> = can_be_prefixed; + +} // namespace detail } // namespace units diff --git a/src/systems/CMakeLists.txt b/src/systems/CMakeLists.txt index 41adc78e..06a3169d 100644 --- a/src/systems/CMakeLists.txt +++ b/src/systems/CMakeLists.txt @@ -20,7 +20,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) # systems add_subdirectory(isq) diff --git a/src/systems/isq-iec80000/CMakeLists.txt b/src/systems/isq-iec80000/CMakeLists.txt index 9f37c6f6..b2caa696 100644 --- a/src/systems/isq-iec80000/CMakeLists.txt +++ b/src/systems/isq-iec80000/CMakeLists.txt @@ -20,6 +20,12 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) -add_units_module(isq-iec80000 mp-units::si) +add_units_module( + isq-iec80000 + DEPENDENCIES mp-units::si + HEADERS include/units/isq/iec80000/binary_prefixes.h include/units/isq/iec80000/iec80000.h + include/units/isq/iec80000/modulation_rate.h include/units/isq/iec80000/storage_capacity.h + include/units/isq/iec80000/traffic_intensity.h include/units/isq/iec80000/transfer_rate.h +) diff --git a/src/systems/isq-iec80000/include/units/isq/iec80000/binary_prefixes.h b/src/systems/isq-iec80000/include/units/isq/iec80000/binary_prefixes.h index e842cf3e..1ff0679e 100644 --- a/src/systems/isq-iec80000/include/units/isq/iec80000/binary_prefixes.h +++ b/src/systems/isq-iec80000/include/units/isq/iec80000/binary_prefixes.h @@ -26,13 +26,11 @@ namespace units::isq::iec80000 { -struct binary_prefix : prefix_family {}; - -struct kibi : units::prefix {}; -struct mebi : units::prefix {}; -struct gibi : units::prefix {}; -struct tebi : units::prefix {}; -struct pebi : units::prefix {}; -struct exbi : units::prefix {}; +struct kibi : units::prefix {}; +struct mebi : units::prefix {}; +struct gibi : units::prefix {}; +struct tebi : units::prefix {}; +struct pebi : units::prefix {}; +struct exbi : units::prefix {}; } // namespace units::isq::iec80000 diff --git a/src/systems/isq-iec80000/include/units/isq/iec80000/modulation_rate.h b/src/systems/isq-iec80000/include/units/isq/iec80000/modulation_rate.h index dcb3d805..40bf6d24 100644 --- a/src/systems/isq-iec80000/include/units/isq/iec80000/modulation_rate.h +++ b/src/systems/isq-iec80000/include/units/isq/iec80000/modulation_rate.h @@ -34,7 +34,7 @@ namespace units::isq::iec80000 { -struct baud : alias_unit {}; +struct baud : alias_unit {}; struct kilobaud : prefixed_alias_unit {}; struct megabaud : prefixed_alias_unit {}; struct gigabaud : prefixed_alias_unit {}; diff --git a/src/systems/isq-iec80000/include/units/isq/iec80000/storage_capacity.h b/src/systems/isq-iec80000/include/units/isq/iec80000/storage_capacity.h index 3e107d20..eaf7a7ca 100644 --- a/src/systems/isq-iec80000/include/units/isq/iec80000/storage_capacity.h +++ b/src/systems/isq-iec80000/include/units/isq/iec80000/storage_capacity.h @@ -35,7 +35,8 @@ namespace units::isq::iec80000 { -struct bit : named_unit {}; +struct bit : named_unit {}; + struct kilobit : prefixed_unit {}; struct megabit : prefixed_unit {}; struct gigabit : prefixed_unit {}; @@ -45,15 +46,15 @@ struct exabit : prefixed_unit {}; struct zettabit : prefixed_unit {}; struct yottabit : prefixed_unit {}; -struct binary_prefix_bit : alias_unit {}; -struct kibibit : prefixed_unit {}; -struct mebibit : prefixed_unit {}; -struct gibibit : prefixed_unit {}; -struct tebibit : prefixed_unit {}; -struct pebibit : prefixed_unit {}; -struct exbibit : prefixed_unit {}; +struct kibibit : prefixed_unit {}; +struct mebibit : prefixed_unit {}; +struct gibibit : prefixed_unit {}; +struct tebibit : prefixed_unit {}; +struct pebibit : prefixed_unit {}; +struct exbibit : prefixed_unit {}; + +struct byte : named_scaled_unit(), bit> {}; -struct byte : named_scaled_unit(), bit> {}; struct kilobyte : prefixed_unit {}; struct megabyte : prefixed_unit {}; struct gigabyte : prefixed_unit {}; @@ -63,13 +64,12 @@ struct exabyte : prefixed_unit {}; struct zettabyte : prefixed_unit {}; struct yottabyte : prefixed_unit {}; -struct binary_prefix_byte : alias_unit {}; -struct kibibyte : prefixed_unit {}; -struct mebibyte : prefixed_unit {}; -struct gibibyte : prefixed_unit {}; -struct tebibyte : prefixed_unit {}; -struct pebibyte : prefixed_unit {}; -// struct exbibyte : prefixed_unit {}; +struct kibibyte : prefixed_unit {}; +struct mebibyte : prefixed_unit {}; +struct gibibyte : prefixed_unit {}; +struct tebibyte : prefixed_unit {}; +struct pebibyte : prefixed_unit {}; +// struct exbibyte : prefixed_unit {}; struct dim_storage_capacity : base_dimension<"M", byte> {}; diff --git a/src/systems/isq-iec80000/include/units/isq/iec80000/traffic_intensity.h b/src/systems/isq-iec80000/include/units/isq/iec80000/traffic_intensity.h index 3c17f62d..03a31646 100644 --- a/src/systems/isq-iec80000/include/units/isq/iec80000/traffic_intensity.h +++ b/src/systems/isq-iec80000/include/units/isq/iec80000/traffic_intensity.h @@ -33,7 +33,7 @@ namespace units::isq::iec80000 { -struct erlang : named_unit {}; +struct erlang : named_unit {}; struct dim_traffic_intensity : base_dimension<"A", erlang> {}; diff --git a/src/systems/isq-iec80000/include/units/isq/iec80000/transfer_rate.h b/src/systems/isq-iec80000/include/units/isq/iec80000/transfer_rate.h index bd2bb20c..54a02d7e 100644 --- a/src/systems/isq-iec80000/include/units/isq/iec80000/transfer_rate.h +++ b/src/systems/isq-iec80000/include/units/isq/iec80000/transfer_rate.h @@ -34,19 +34,19 @@ namespace units::isq::iec80000 { -struct byte_per_second : unit {}; +struct byte_per_second : derived_unit {}; struct dim_transfer_rate : derived_dimension, exponent> {}; -struct kilobyte_per_second : derived_unit {}; -struct megabyte_per_second : derived_unit {}; -struct gigabyte_per_second : derived_unit {}; -struct terabyte_per_second : derived_unit {}; -struct petabyte_per_second : derived_unit {}; -struct exabyte_per_second : derived_unit {}; -struct zettabyte_per_second : derived_unit {}; -struct yottabyte_per_second : derived_unit {}; +struct kilobyte_per_second : derived_scaled_unit {}; +struct megabyte_per_second : derived_scaled_unit {}; +struct gigabyte_per_second : derived_scaled_unit {}; +struct terabyte_per_second : derived_scaled_unit {}; +struct petabyte_per_second : derived_scaled_unit {}; +struct exabyte_per_second : derived_scaled_unit {}; +struct zettabyte_per_second : derived_scaled_unit {}; +struct yottabyte_per_second : derived_scaled_unit {}; template concept TransferRate = QuantityOf; diff --git a/src/systems/isq-natural/CMakeLists.txt b/src/systems/isq-natural/CMakeLists.txt index 7f9353b4..e968bdff 100644 --- a/src/systems/isq-natural/CMakeLists.txt +++ b/src/systems/isq-natural/CMakeLists.txt @@ -20,6 +20,20 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) -add_units_module(isq-natural mp-units::isq) +add_units_module( + isq-natural + DEPENDENCIES mp-units::isq + HEADERS include/units/isq/natural/acceleration.h + include/units/isq/natural/constants.h + include/units/isq/natural/energy.h + include/units/isq/natural/force.h + include/units/isq/natural/length.h + include/units/isq/natural/mass.h + include/units/isq/natural/momentum.h + include/units/isq/natural/natural.h + include/units/isq/natural/speed.h + include/units/isq/natural/time.h + include/units/isq/natural/units.h +) diff --git a/src/systems/isq-natural/include/units/isq/natural/units.h b/src/systems/isq-natural/include/units/isq/natural/units.h index 1d64e28b..82712296 100644 --- a/src/systems/isq-natural/include/units/isq/natural/units.h +++ b/src/systems/isq-natural/include/units/isq/natural/units.h @@ -31,11 +31,10 @@ namespace units::isq::natural { -struct electronvolt : named_unit {}; +struct electronvolt : named_unit {}; struct gigaelectronvolt : prefixed_unit {}; -struct inverted_gigaelectronvolt : - named_unit {}; -struct square_gigaelectronvolt : named_unit {}; +struct inverted_gigaelectronvolt : named_unit {}; +struct square_gigaelectronvolt : named_unit {}; // NOTE: eV as a base unit with no relation to joule prevents us from going back // from natural units to SI. Do we need such a support or should we treat diff --git a/src/systems/isq/CMakeLists.txt b/src/systems/isq/CMakeLists.txt index 1c8e49b5..c7dffcfc 100644 --- a/src/systems/isq/CMakeLists.txt +++ b/src/systems/isq/CMakeLists.txt @@ -20,6 +20,54 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) -add_units_module(isq mp-units::core) +add_units_module( + isq + DEPENDENCIES mp-units::core + HEADERS include/units/isq/dimensions/absorbed_dose.h + include/units/isq/dimensions/acceleration.h + include/units/isq/dimensions/amount_of_substance.h + include/units/isq/dimensions/angular_velocity.h + include/units/isq/dimensions/area.h + include/units/isq/dimensions/capacitance.h + include/units/isq/dimensions/catalytic_activity.h + include/units/isq/dimensions/charge_density.h + include/units/isq/dimensions/concentration.h + include/units/isq/dimensions/conductance.h + include/units/isq/dimensions/current_density.h + include/units/isq/dimensions/density.h + include/units/isq/dimensions/dynamic_viscosity.h + include/units/isq/dimensions/electric_charge.h + include/units/isq/dimensions/electric_current.h + include/units/isq/dimensions/electric_field_strength.h + include/units/isq/dimensions/energy.h + include/units/isq/dimensions/energy_density.h + include/units/isq/dimensions/force.h + include/units/isq/dimensions/frequency.h + include/units/isq/dimensions/heat_capacity.h + include/units/isq/dimensions/inductance.h + include/units/isq/dimensions/length.h + include/units/isq/dimensions/luminance.h + include/units/isq/dimensions/luminous_intensity.h + include/units/isq/dimensions/magnetic_flux.h + include/units/isq/dimensions/magnetic_induction.h + include/units/isq/dimensions/mass.h + include/units/isq/dimensions/molar_energy.h + include/units/isq/dimensions/momentum.h + include/units/isq/dimensions/permeability.h + include/units/isq/dimensions/permittivity.h + include/units/isq/dimensions/power.h + include/units/isq/dimensions/pressure.h + include/units/isq/dimensions/radioactivity.h + include/units/isq/dimensions/resistance.h + include/units/isq/dimensions/speed.h + include/units/isq/dimensions/surface_tension.h + include/units/isq/dimensions/thermal_conductivity.h + include/units/isq/dimensions/thermodynamic_temperature.h + include/units/isq/dimensions/time.h + include/units/isq/dimensions/torque.h + include/units/isq/dimensions/voltage.h + include/units/isq/dimensions/volume.h + include/units/isq/dimensions.h +) diff --git a/src/systems/isq/include/units/isq/dimensions/momentum.h b/src/systems/isq/include/units/isq/dimensions/momentum.h index f7240259..8508fb0a 100644 --- a/src/systems/isq/include/units/isq/dimensions/momentum.h +++ b/src/systems/isq/include/units/isq/dimensions/momentum.h @@ -23,6 +23,7 @@ #pragma once #include +#include #include namespace units::isq { diff --git a/src/systems/si-cgs/CMakeLists.txt b/src/systems/si-cgs/CMakeLists.txt index 10b16ae9..08316c20 100644 --- a/src/systems/si-cgs/CMakeLists.txt +++ b/src/systems/si-cgs/CMakeLists.txt @@ -20,6 +20,20 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) -add_units_module(si-cgs mp-units::si) +add_units_module( + si-cgs + DEPENDENCIES mp-units::si + HEADERS include/units/isq/si/cgs/acceleration.h + include/units/isq/si/cgs/area.h + include/units/isq/si/cgs/cgs.h + include/units/isq/si/cgs/energy.h + include/units/isq/si/cgs/force.h + include/units/isq/si/cgs/length.h + include/units/isq/si/cgs/mass.h + include/units/isq/si/cgs/power.h + include/units/isq/si/cgs/pressure.h + include/units/isq/si/cgs/speed.h + include/units/isq/si/cgs/time.h +) diff --git a/src/systems/si-cgs/include/units/isq/si/cgs/acceleration.h b/src/systems/si-cgs/include/units/isq/si/cgs/acceleration.h index 53d56784..fc983980 100644 --- a/src/systems/si-cgs/include/units/isq/si/cgs/acceleration.h +++ b/src/systems/si-cgs/include/units/isq/si/cgs/acceleration.h @@ -34,7 +34,7 @@ namespace units::isq::si::cgs { -struct gal : named_unit {}; +struct gal : named_unit {}; struct dim_acceleration : isq::dim_acceleration {}; template U, Representation Rep = double> diff --git a/src/systems/si-cgs/include/units/isq/si/cgs/energy.h b/src/systems/si-cgs/include/units/isq/si/cgs/energy.h index d6e0c16b..7ca8af7f 100644 --- a/src/systems/si-cgs/include/units/isq/si/cgs/energy.h +++ b/src/systems/si-cgs/include/units/isq/si/cgs/energy.h @@ -35,7 +35,7 @@ namespace units::isq::si::cgs { -struct erg : named_unit {}; +struct erg : named_unit {}; struct dim_energy : isq::dim_energy {}; diff --git a/src/systems/si-cgs/include/units/isq/si/cgs/force.h b/src/systems/si-cgs/include/units/isq/si/cgs/force.h index e00f5a0d..f6f7bca3 100644 --- a/src/systems/si-cgs/include/units/isq/si/cgs/force.h +++ b/src/systems/si-cgs/include/units/isq/si/cgs/force.h @@ -36,7 +36,7 @@ namespace units::isq::si::cgs { -struct dyne : named_unit {}; +struct dyne : named_unit {}; struct dim_force : isq::dim_force {}; diff --git a/src/systems/si-cgs/include/units/isq/si/cgs/power.h b/src/systems/si-cgs/include/units/isq/si/cgs/power.h index 1ac322f6..5d2b0483 100644 --- a/src/systems/si-cgs/include/units/isq/si/cgs/power.h +++ b/src/systems/si-cgs/include/units/isq/si/cgs/power.h @@ -34,7 +34,7 @@ namespace units::isq::si::cgs { -struct erg_per_second : unit {}; +struct erg_per_second : derived_unit {}; struct dim_power : isq::dim_power {}; diff --git a/src/systems/si-cgs/include/units/isq/si/cgs/pressure.h b/src/systems/si-cgs/include/units/isq/si/cgs/pressure.h index 5d4f89ea..e3b1a36a 100644 --- a/src/systems/si-cgs/include/units/isq/si/cgs/pressure.h +++ b/src/systems/si-cgs/include/units/isq/si/cgs/pressure.h @@ -36,7 +36,7 @@ namespace units::isq::si::cgs { -struct barye : named_unit {}; +struct barye : named_unit {}; struct dim_pressure : isq::dim_pressure {}; diff --git a/src/systems/si-cgs/include/units/isq/si/cgs/speed.h b/src/systems/si-cgs/include/units/isq/si/cgs/speed.h index 6cdc4a7d..c70ee197 100644 --- a/src/systems/si-cgs/include/units/isq/si/cgs/speed.h +++ b/src/systems/si-cgs/include/units/isq/si/cgs/speed.h @@ -34,7 +34,7 @@ namespace units::isq::si::cgs { -struct centimetre_per_second : unit {}; +struct centimetre_per_second : derived_unit {}; struct dim_speed : isq::dim_speed {}; template U, Representation Rep = double> diff --git a/src/systems/si-fps/CMakeLists.txt b/src/systems/si-fps/CMakeLists.txt index c311fb5e..ffd302de 100644 --- a/src/systems/si-fps/CMakeLists.txt +++ b/src/systems/si-fps/CMakeLists.txt @@ -20,6 +20,22 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) -add_units_module(si-fps mp-units::si) +add_units_module( + si-fps + DEPENDENCIES mp-units::si-international + HEADERS include/units/isq/si/fps/acceleration.h + include/units/isq/si/fps/area.h + include/units/isq/si/fps/density.h + include/units/isq/si/fps/energy.h + include/units/isq/si/fps/force.h + include/units/isq/si/fps/fps.h + include/units/isq/si/fps/length.h + include/units/isq/si/fps/mass.h + include/units/isq/si/fps/power.h + include/units/isq/si/fps/pressure.h + include/units/isq/si/fps/speed.h + include/units/isq/si/fps/time.h + include/units/isq/si/fps/volume.h +) diff --git a/src/systems/si-fps/include/units/isq/si/fps/acceleration.h b/src/systems/si-fps/include/units/isq/si/fps/acceleration.h index 97990439..da1c9593 100644 --- a/src/systems/si-fps/include/units/isq/si/fps/acceleration.h +++ b/src/systems/si-fps/include/units/isq/si/fps/acceleration.h @@ -33,7 +33,7 @@ namespace units::isq::si::fps { -struct foot_per_second_sq : unit {}; +struct foot_per_second_sq : derived_unit {}; struct dim_acceleration : isq::dim_acceleration {}; template U, Representation Rep = double> diff --git a/src/systems/si-fps/include/units/isq/si/fps/area.h b/src/systems/si-fps/include/units/isq/si/fps/area.h index acafd67f..076dab96 100644 --- a/src/systems/si-fps/include/units/isq/si/fps/area.h +++ b/src/systems/si-fps/include/units/isq/si/fps/area.h @@ -34,7 +34,7 @@ namespace units::isq::si::fps { -struct square_foot : unit {}; +struct square_foot : derived_unit {}; struct dim_area : isq::dim_area {}; diff --git a/src/systems/si-fps/include/units/isq/si/fps/density.h b/src/systems/si-fps/include/units/isq/si/fps/density.h index f2aa0e65..41ee340e 100644 --- a/src/systems/si-fps/include/units/isq/si/fps/density.h +++ b/src/systems/si-fps/include/units/isq/si/fps/density.h @@ -34,7 +34,7 @@ namespace units::isq::si::fps { -struct pound_per_foot_cub : unit {}; +struct pound_per_foot_cub : derived_unit {}; struct dim_density : isq::dim_density {}; diff --git a/src/systems/si-fps/include/units/isq/si/fps/energy.h b/src/systems/si-fps/include/units/isq/si/fps/energy.h index 7278f016..593319a0 100644 --- a/src/systems/si-fps/include/units/isq/si/fps/energy.h +++ b/src/systems/si-fps/include/units/isq/si/fps/energy.h @@ -35,12 +35,12 @@ namespace units::isq::si::fps { // https://en.wikipedia.org/wiki/Foot-poundal -struct foot_poundal : unit {}; +struct foot_poundal : derived_unit {}; struct dim_energy : isq::dim_energy {}; // https://en.wikipedia.org/wiki/Foot-pound_(energy) -struct foot_pound_force : derived_unit {}; +struct foot_pound_force : derived_scaled_unit {}; template U, Representation Rep = double> using energy = quantity; diff --git a/src/systems/si-fps/include/units/isq/si/fps/force.h b/src/systems/si-fps/include/units/isq/si/fps/force.h index 330ad453..a026bd79 100644 --- a/src/systems/si-fps/include/units/isq/si/fps/force.h +++ b/src/systems/si-fps/include/units/isq/si/fps/force.h @@ -37,16 +37,15 @@ namespace units::isq::si::fps { // https://en.wikipedia.org/wiki/Poundal -struct poundal : named_unit {}; +struct poundal : named_unit {}; // https://en.wikipedia.org/wiki/Pound_(force) -struct pound_force : - named_scaled_unit(), poundal> {}; +struct pound_force : named_scaled_unit(), poundal> {}; struct kilopound_force : prefixed_unit {}; // https://en.wikipedia.org/wiki/Kip_(unit), -struct kip : alias_unit {}; +struct kip : alias_unit {}; struct dim_force : isq::dim_force {}; diff --git a/src/systems/si-fps/include/units/isq/si/fps/length.h b/src/systems/si-fps/include/units/isq/si/fps/length.h index 12b83ae5..35f51d7f 100644 --- a/src/systems/si-fps/include/units/isq/si/fps/length.h +++ b/src/systems/si-fps/include/units/isq/si/fps/length.h @@ -29,30 +29,27 @@ #include // IWYU pragma: end_exports -#include +#include #include namespace units::isq::si::fps { // https://en.wikipedia.org/wiki/Foot_(unit) -struct foot : named_scaled_unit(), si::metre> {}; - -struct inch : named_scaled_unit(), foot> {}; +using si::international::fathom; +using si::international::foot; +using si::international::inch; +using si::international::mil; +using si::international::thou; +using si::international::yard; // thousandth of an inch -struct thousandth : named_scaled_unit(), inch> {}; -struct thou : alias_unit {}; -struct mil : alias_unit {}; - -struct yard : named_scaled_unit(), foot> {}; - -struct fathom : named_scaled_unit(), foot> {}; +struct thousandth : alias_unit {}; struct kiloyard : prefixed_unit {}; -struct mile : named_scaled_unit(), foot> {}; +struct mile : named_scaled_unit(), foot> {}; -struct nautical_mile : named_scaled_unit(), yard> {}; +struct nautical_mile : named_scaled_unit(), yard> {}; struct dim_length : isq::dim_length {}; diff --git a/src/systems/si-fps/include/units/isq/si/fps/mass.h b/src/systems/si-fps/include/units/isq/si/fps/mass.h index bc669e7f..16b23f0a 100644 --- a/src/systems/si-fps/include/units/isq/si/fps/mass.h +++ b/src/systems/si-fps/include/units/isq/si/fps/mass.h @@ -35,29 +35,28 @@ namespace units::isq::si::fps { // https://en.wikipedia.org/wiki/Pound_(mass) -struct pound : - named_scaled_unit(), si::kilogram> {}; +struct pound : named_scaled_unit(), si::kilogram> {}; struct dim_mass : isq::dim_mass {}; template U, Representation Rep = double> using mass = quantity; -struct grain : named_scaled_unit(), pound> {}; +struct grain : named_scaled_unit(), pound> {}; -struct dram : named_scaled_unit(), pound> {}; +struct dram : named_scaled_unit(), pound> {}; -struct ounce : named_scaled_unit(), pound> {}; +struct ounce : named_scaled_unit(), pound> {}; -struct stone : named_scaled_unit(), pound> {}; +struct stone : named_scaled_unit(), pound> {}; -struct quarter : named_scaled_unit(), pound> {}; +struct quarter : named_scaled_unit(), pound> {}; -struct hundredweight : named_scaled_unit(), pound> {}; +struct hundredweight : named_scaled_unit(), pound> {}; -struct short_ton : named_scaled_unit(), pound> {}; +struct short_ton : named_scaled_unit(), pound> {}; -struct long_ton : named_scaled_unit(), pound> {}; +struct long_ton : named_scaled_unit(), pound> {}; #ifndef UNITS_NO_LITERALS diff --git a/src/systems/si-fps/include/units/isq/si/fps/power.h b/src/systems/si-fps/include/units/isq/si/fps/power.h index ac589004..931c08f4 100644 --- a/src/systems/si-fps/include/units/isq/si/fps/power.h +++ b/src/systems/si-fps/include/units/isq/si/fps/power.h @@ -35,14 +35,14 @@ namespace units::isq::si::fps { -struct foot_poundal_per_second : unit {}; +struct foot_poundal_per_second : derived_unit {}; struct dim_power : isq::dim_power {}; -struct foot_pound_force_per_second : derived_unit {}; +struct foot_pound_force_per_second : + derived_scaled_unit {}; -struct horse_power : - named_scaled_unit(), foot_pound_force_per_second> {}; +struct horse_power : named_scaled_unit(), foot_pound_force_per_second> {}; template U, Representation Rep = double> using power = quantity; diff --git a/src/systems/si-fps/include/units/isq/si/fps/pressure.h b/src/systems/si-fps/include/units/isq/si/fps/pressure.h index 93c48eaf..4b036fc1 100644 --- a/src/systems/si-fps/include/units/isq/si/fps/pressure.h +++ b/src/systems/si-fps/include/units/isq/si/fps/pressure.h @@ -36,7 +36,7 @@ namespace units::isq::si::fps { -struct poundal_per_foot_sq : unit {}; +struct poundal_per_foot_sq : derived_unit {}; struct dim_pressure : isq::dim_pressure {}; @@ -44,12 +44,11 @@ template U, Representation Rep = double> using pressure = quantity; struct pound_force_per_foot_sq : - named_scaled_unit(), + named_scaled_unit(), poundal_per_foot_sq> {}; struct pound_force_per_inch_sq : - named_scaled_unit(), - pound_force_per_foot_sq> {}; + named_scaled_unit(), pound_force_per_foot_sq> {}; struct kilopound_force_per_inch_sq : prefixed_unit {}; diff --git a/src/systems/si-fps/include/units/isq/si/fps/speed.h b/src/systems/si-fps/include/units/isq/si/fps/speed.h index 04302b86..6ec5944d 100644 --- a/src/systems/si-fps/include/units/isq/si/fps/speed.h +++ b/src/systems/si-fps/include/units/isq/si/fps/speed.h @@ -35,15 +35,15 @@ namespace units::isq::si::fps { -struct foot_per_second : unit {}; +struct foot_per_second : derived_unit {}; struct dim_speed : isq::dim_speed {}; template U, Representation Rep = double> using speed = quantity; -struct mile_per_hour : derived_unit {}; -struct nautical_mile_per_hour : derived_unit {}; -struct knot : alias_unit {}; +struct mile_per_hour : derived_scaled_unit {}; +struct nautical_mile_per_hour : derived_scaled_unit {}; +struct knot : alias_unit {}; #ifndef UNITS_NO_LITERALS @@ -66,12 +66,12 @@ constexpr auto operator"" _q_mph(unsigned long long l) constexpr auto operator"" _q_mph(long double l) { return speed(l); } // kn -constexpr auto operator"" _q_knot(unsigned long long l) +constexpr auto operator"" _q_kn(unsigned long long l) { gsl_ExpectsAudit(std::in_range(l)); return speed(static_cast(l)); } -constexpr auto operator"" _q_knot(long double l) { return speed(l); } +constexpr auto operator"" _q_kn(long double l) { return speed(l); } } // namespace literals @@ -82,7 +82,7 @@ constexpr auto operator"" _q_knot(long double l) { return speed{}; -inline constexpr auto knot = reference{}; +inline constexpr auto kn = reference{}; } // namespace speed_references @@ -105,7 +105,7 @@ using ft_per_s = units::isq::si::fps::speed using mph = units::isq::si::fps::speed; template -using knot = units::isq::si::fps::speed; +using kn = units::isq::si::fps::speed; } // namespace units::aliases::isq::si::fps::inline speed diff --git a/src/systems/si-fps/include/units/isq/si/fps/volume.h b/src/systems/si-fps/include/units/isq/si/fps/volume.h index a461790c..7df571e2 100644 --- a/src/systems/si-fps/include/units/isq/si/fps/volume.h +++ b/src/systems/si-fps/include/units/isq/si/fps/volume.h @@ -34,10 +34,10 @@ namespace units::isq::si::fps { -struct cubic_foot : unit {}; +struct cubic_foot : derived_unit {}; struct dim_volume : isq::dim_volume {}; -struct cubic_yard : derived_unit {}; +struct cubic_yard : derived_scaled_unit {}; template U, Representation Rep = double> using volume = quantity; diff --git a/src/systems/si-hep/CMakeLists.txt b/src/systems/si-hep/CMakeLists.txt index 0403a82b..635d2981 100644 --- a/src/systems/si-hep/CMakeLists.txt +++ b/src/systems/si-hep/CMakeLists.txt @@ -20,6 +20,10 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) -add_units_module(si-hep mp-units::si) +add_units_module( + si-hep DEPENDENCIES mp-units::si + HEADERS include/units/isq/si/hep/area.h include/units/isq/si/hep/energy.h include/units/isq/si/hep/hep.h + include/units/isq/si/hep/mass.h include/units/isq/si/hep/momentum.h +) diff --git a/src/systems/si-hep/include/units/isq/si/hep/area.h b/src/systems/si-hep/include/units/isq/si/hep/area.h index e1e7a297..e08b59eb 100644 --- a/src/systems/si-hep/include/units/isq/si/hep/area.h +++ b/src/systems/si-hep/include/units/isq/si/hep/area.h @@ -29,7 +29,7 @@ #include // IWYU pragma: end_exports -#include +#include #include namespace units::isq::si::hep { @@ -37,7 +37,7 @@ namespace units::isq::si::hep { // effective cross-sectional area according to EU council directive 80/181/EEC // https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=CELEX:01980L0181-20090527#page=10 // https://www.fedlex.admin.ch/eli/cc/1994/3109_3109_3109/de -struct barn : named_scaled_unit(), square_metre> {}; +struct barn : named_scaled_unit(), square_metre> {}; struct yocto_barn : prefixed_unit {}; struct zepto_barn : prefixed_unit {}; struct atto_barn : prefixed_unit {}; diff --git a/src/systems/si-hep/include/units/isq/si/hep/mass.h b/src/systems/si-hep/include/units/isq/si/hep/mass.h index 824c2262..e4a895e0 100644 --- a/src/systems/si-hep/include/units/isq/si/hep/mass.h +++ b/src/systems/si-hep/include/units/isq/si/hep/mass.h @@ -43,7 +43,7 @@ inline constexpr std::optional units::known_first_factor<225'653' namespace units::isq::si::hep { struct eV_per_c2 : - named_scaled_unit(), kilogram> {}; struct feV_per_c2 : prefixed_unit {}; struct peV_per_c2 : prefixed_unit {}; @@ -60,14 +60,11 @@ struct PeV_per_c2 : prefixed_unit {}; struct EeV_per_c2 : prefixed_unit {}; struct YeV_per_c2 : prefixed_unit {}; struct electron_mass : - named_scaled_unit(), - kilogram> {}; + named_scaled_unit(), kilogram> {}; struct proton_mass : - named_scaled_unit(), - kilogram> {}; + named_scaled_unit(), kilogram> {}; struct neutron_mass : - named_scaled_unit(), - kilogram> {}; + named_scaled_unit(), kilogram> {}; struct dim_mass : isq::dim_mass {}; diff --git a/src/systems/si-hep/include/units/isq/si/hep/momentum.h b/src/systems/si-hep/include/units/isq/si/hep/momentum.h index 9cabfb15..21dc44c6 100644 --- a/src/systems/si-hep/include/units/isq/si/hep/momentum.h +++ b/src/systems/si-hep/include/units/isq/si/hep/momentum.h @@ -24,7 +24,6 @@ // IWYU pragma: begin_exports #include -#include #include #include // IWYU pragma: end_exports @@ -35,9 +34,11 @@ namespace units::isq::si::hep { +struct kilogram_metre_per_second : derived_unit {}; + struct eV_per_c : - named_scaled_unit(), - ::units::isq::si::kilogram_metre_per_second> {}; + named_scaled_unit(), + kilogram_metre_per_second> {}; struct feV_per_c : prefixed_unit {}; struct peV_per_c : prefixed_unit {}; struct neV_per_c : prefixed_unit {}; diff --git a/src/systems/si-iau/CMakeLists.txt b/src/systems/si-iau/CMakeLists.txt index ce9984a8..7e86c0d2 100644 --- a/src/systems/si-iau/CMakeLists.txt +++ b/src/systems/si-iau/CMakeLists.txt @@ -20,6 +20,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) -add_units_module(si-iau mp-units::si) +add_units_module( + si-iau DEPENDENCIES mp-units::si HEADERS include/units/isq/si/iau/iau.h include/units/isq/si/iau/length.h +) diff --git a/src/systems/si-iau/include/units/isq/si/iau/length.h b/src/systems/si-iau/include/units/isq/si/iau/length.h index 22350735..d2e184a1 100644 --- a/src/systems/si-iau/include/units/isq/si/iau/length.h +++ b/src/systems/si-iau/include/units/isq/si/iau/length.h @@ -36,13 +36,13 @@ namespace units::isq::si::iau { // https://en.wikipedia.org/wiki/Light-year -struct light_year : named_scaled_unit(), si::metre> {}; +struct light_year : named_scaled_unit(), si::metre> {}; // https://en.wikipedia.org/wiki/Parsec -struct parsec : named_scaled_unit(), si::metre> {}; +struct parsec : named_scaled_unit(), si::metre> {}; // https://en.wikipedia.org/wiki/Angstrom -struct angstrom : named_scaled_unit(), si::metre> {}; +struct angstrom : named_scaled_unit(), si::metre> {}; #ifndef UNITS_NO_LITERALS diff --git a/src/systems/si-imperial/CMakeLists.txt b/src/systems/si-imperial/CMakeLists.txt index f99f274b..3a441611 100644 --- a/src/systems/si-imperial/CMakeLists.txt +++ b/src/systems/si-imperial/CMakeLists.txt @@ -20,6 +20,9 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) -add_units_module(si-imperial mp-units::si) +add_units_module( + si-imperial DEPENDENCIES mp-units::si HEADERS include/units/isq/si/imperial/imperial.h + include/units/isq/si/imperial/length.h +) diff --git a/src/systems/si-imperial/include/units/isq/si/imperial/length.h b/src/systems/si-imperial/include/units/isq/si/imperial/length.h index 4136595a..5f4be435 100644 --- a/src/systems/si-imperial/include/units/isq/si/imperial/length.h +++ b/src/systems/si-imperial/include/units/isq/si/imperial/length.h @@ -35,10 +35,10 @@ namespace units::isq::si::imperial { // https://en.wikipedia.org/wiki/Chain_(unit) -struct chain : named_scaled_unit(), si::international::yard> {}; +struct chain : named_scaled_unit(), si::international::yard> {}; // https://en.wikipedia.org/wiki/Rod_(unit) -struct rod : named_scaled_unit(), chain> {}; +struct rod : named_scaled_unit(), chain> {}; #ifndef UNITS_NO_LITERALS diff --git a/src/systems/si-international/CMakeLists.txt b/src/systems/si-international/CMakeLists.txt index e8b2716a..82c940fd 100644 --- a/src/systems/si-international/CMakeLists.txt +++ b/src/systems/si-international/CMakeLists.txt @@ -20,6 +20,12 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) -add_units_module(si-international mp-units::si) +add_units_module( + si-international + DEPENDENCIES mp-units::si + HEADERS include/units/isq/si/international/area.h include/units/isq/si/international/international.h + include/units/isq/si/international/length.h include/units/isq/si/international/speed.h + include/units/isq/si/international/volume.h +) diff --git a/src/systems/si-international/include/units/isq/si/international/area.h b/src/systems/si-international/include/units/isq/si/international/area.h index 74bd6ad1..40fdc533 100644 --- a/src/systems/si-international/include/units/isq/si/international/area.h +++ b/src/systems/si-international/include/units/isq/si/international/area.h @@ -35,7 +35,7 @@ namespace units::isq::si::international { -struct square_foot : derived_unit {}; +struct square_foot : derived_scaled_unit {}; #ifndef UNITS_NO_LITERALS diff --git a/src/systems/si-international/include/units/isq/si/international/length.h b/src/systems/si-international/include/units/isq/si/international/length.h index 7ea729b7..b61bd2cf 100644 --- a/src/systems/si-international/include/units/isq/si/international/length.h +++ b/src/systems/si-international/include/units/isq/si/international/length.h @@ -37,30 +37,30 @@ namespace units::isq::si::international { // si::international yard // https://en.wikipedia.org/wiki/International_yard_and_pound -struct yard : named_scaled_unit(), si::metre> {}; +struct yard : named_scaled_unit(), si::metre> {}; // si::international foot // https://en.wikipedia.org/wiki/Foot_(unit)#International_foot -struct foot : named_scaled_unit(), yard> {}; +struct foot : named_scaled_unit(), yard> {}; // https://en.wikipedia.org/wiki/Fathom#International_fathom -struct fathom : named_scaled_unit(), yard> {}; +struct fathom : named_scaled_unit(), yard> {}; // si::international inch // https://en.wikipedia.org/wiki/Inch#Equivalences -struct inch : named_scaled_unit(), yard> {}; +struct inch : named_scaled_unit(), yard> {}; // intrnational mile // https://en.wikipedia.org/wiki/Mile#International_mile -struct mile : named_scaled_unit(), si::kilometre> {}; +struct mile : named_scaled_unit(), si::kilometre> {}; // si::international nautical mile // https://en.wikipedia.org/wiki/Nautical_mile -struct nautical_mile : named_scaled_unit(), si::metre> {}; +struct nautical_mile : named_scaled_unit(), si::metre> {}; // thou // https://en.wikipedia.org/wiki/Thousandth_of_an_inch -struct thou : named_scaled_unit(), inch> {}; +struct thou : named_scaled_unit(), inch> {}; // mil - different name for thou // https://en.wikipedia.org/wiki/Thousandth_of_an_inch diff --git a/src/systems/si-international/include/units/isq/si/international/speed.h b/src/systems/si-international/include/units/isq/si/international/speed.h index 3ce51418..84f2dbf1 100644 --- a/src/systems/si-international/include/units/isq/si/international/speed.h +++ b/src/systems/si-international/include/units/isq/si/international/speed.h @@ -34,7 +34,10 @@ namespace units::isq::si::international { -struct mile_per_hour : derived_unit {}; +struct mile_per_hour : derived_scaled_unit {}; +struct nautical_mile_per_hour : + derived_scaled_unit {}; +struct knot : alias_unit {}; #ifndef UNITS_NO_LITERALS @@ -48,10 +51,42 @@ constexpr auto operator"" _q_mi_per_h(unsigned long long l) } constexpr auto operator"" _q_mi_per_h(long double l) { return si::speed(l); } +// nmi/h +constexpr auto operator"" _q_nmi_per_h(unsigned long long l) +{ + gsl_ExpectsAudit(std::in_range(l)); + return si::speed(static_cast(l)); +} +constexpr auto operator"" _q_nmi_per_h(long double l) { return si::speed(l); } + +// kn +constexpr auto operator"" _q_kn(unsigned long long l) +{ + gsl_ExpectsAudit(std::in_range(l)); + return si::speed(static_cast(l)); +} +constexpr auto operator"" _q_kn(long double l) { return si::speed(l); } + } // namespace literals #endif // UNITS_NO_LITERALS +#ifndef UNITS_NO_REFERENCES + +namespace speed_references { + +inline constexpr auto kn = reference{}; + +} // namespace speed_references + +namespace references { + +using namespace speed_references; + +} // namespace references + +#endif // UNITS_NO_REFERENCES + } // namespace units::isq::si::international #ifndef UNITS_NO_ALIASES @@ -61,6 +96,12 @@ namespace units::aliases::isq::si::international::inline speed { template using mi_per_h = units::isq::si::speed; +template +using nmi_per_h = units::isq::si::speed; + +template +using kn = units::isq::si::speed; + } // namespace units::aliases::isq::si::international::inline speed #endif // UNITS_NO_ALIASES diff --git a/src/systems/si-international/include/units/isq/si/international/volume.h b/src/systems/si-international/include/units/isq/si/international/volume.h index 7c7b65cc..4a5fcbcd 100644 --- a/src/systems/si-international/include/units/isq/si/international/volume.h +++ b/src/systems/si-international/include/units/isq/si/international/volume.h @@ -35,7 +35,7 @@ namespace units::isq::si::international { -struct cubic_foot : derived_unit {}; +struct cubic_foot : derived_scaled_unit {}; #ifndef UNITS_NO_LITERALS diff --git a/src/systems/si-typographic/CMakeLists.txt b/src/systems/si-typographic/CMakeLists.txt index 10d0e4d7..7e359ea2 100644 --- a/src/systems/si-typographic/CMakeLists.txt +++ b/src/systems/si-typographic/CMakeLists.txt @@ -20,6 +20,9 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) -add_units_module(si-typographic mp-units::si) +add_units_module( + si-typographic DEPENDENCIES mp-units::si HEADERS include/units/isq/si/typographic/length.h + include/units/isq/si/typographic/typographic.h +) diff --git a/src/systems/si-typographic/include/units/isq/si/typographic/length.h b/src/systems/si-typographic/include/units/isq/si/typographic/length.h index e8b4b5a8..e69c31c6 100644 --- a/src/systems/si-typographic/include/units/isq/si/typographic/length.h +++ b/src/systems/si-typographic/include/units/isq/si/typographic/length.h @@ -38,13 +38,11 @@ namespace units::isq::si::typographic { // TODO Conflicts with (https://en.wikipedia.org/wiki/Pica_(typography)), verify correctness of below conversion factors // and provide hyperlinks to definitions struct pica_comp : - named_scaled_unit(), si::metre> {}; -struct pica_prn : - named_scaled_unit(), si::metre> {}; + named_scaled_unit(), si::metre> {}; +struct pica_prn : named_scaled_unit(), si::metre> {}; struct point_comp : - named_scaled_unit(), si::metre> {}; -struct point_prn : - named_scaled_unit(), si::metre> {}; + named_scaled_unit(), si::metre> {}; +struct point_prn : named_scaled_unit(), si::metre> {}; #ifndef UNITS_NO_LITERALS diff --git a/src/systems/si-uscs/CMakeLists.txt b/src/systems/si-uscs/CMakeLists.txt index d5abf74c..1a10f79e 100644 --- a/src/systems/si-uscs/CMakeLists.txt +++ b/src/systems/si-uscs/CMakeLists.txt @@ -20,6 +20,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) -add_units_module(si-uscs mp-units::si) +add_units_module( + si-uscs DEPENDENCIES mp-units::si HEADERS include/units/isq/si/uscs/length.h include/units/isq/si/uscs/uscs.h +) diff --git a/src/systems/si-uscs/include/units/isq/si/uscs/length.h b/src/systems/si-uscs/include/units/isq/si/uscs/length.h index 83281090..fe4eb9f1 100644 --- a/src/systems/si-uscs/include/units/isq/si/uscs/length.h +++ b/src/systems/si-uscs/include/units/isq/si/uscs/length.h @@ -36,14 +36,14 @@ namespace units::isq::si::uscs { // https://en.wikipedia.org/wiki/Foot_(unit)#US_survey_foot // https://www.nist.gov/pml/special-publication-811/nist-guide-si-appendix-b-conversion-factors#B6 -struct foot : named_scaled_unit(), si::metre> {}; +struct foot : named_scaled_unit(), si::metre> {}; // https://www.nist.gov/pml/special-publication-811/nist-guide-si-appendix-b-conversion-factors#B6 -struct fathom : named_scaled_unit(), foot> {}; +struct fathom : named_scaled_unit(), foot> {}; // https://en.wikipedia.org/wiki/Mile#U.S._survey_mile // https://www.nist.gov/pml/special-publication-811/nist-guide-si-appendix-b-conversion-factors#B6 -struct mile : named_scaled_unit(), foot> {}; +struct mile : named_scaled_unit(), foot> {}; #ifndef UNITS_NO_LITERALS diff --git a/src/systems/si/CMakeLists.txt b/src/systems/si/CMakeLists.txt index bb5098b5..f591c780 100644 --- a/src/systems/si/CMakeLists.txt +++ b/src/systems/si/CMakeLists.txt @@ -20,6 +20,56 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.19) -add_units_module(si mp-units::isq) +add_units_module( + si + DEPENDENCIES mp-units::isq + HEADERS include/units/isq/si/absorbed_dose.h + include/units/isq/si/acceleration.h + include/units/isq/si/amount_of_substance.h + include/units/isq/si/angular_velocity.h + include/units/isq/si/area.h + include/units/isq/si/capacitance.h + include/units/isq/si/catalytic_activity.h + include/units/isq/si/charge_density.h + include/units/isq/si/concentration.h + include/units/isq/si/conductance.h + include/units/isq/si/constants.h + include/units/isq/si/current_density.h + include/units/isq/si/density.h + include/units/isq/si/dynamic_viscosity.h + include/units/isq/si/electric_charge.h + include/units/isq/si/electric_current.h + include/units/isq/si/electric_field_strength.h + include/units/isq/si/energy.h + include/units/isq/si/energy_density.h + include/units/isq/si/force.h + include/units/isq/si/frequency.h + include/units/isq/si/heat_capacity.h + include/units/isq/si/inductance.h + include/units/isq/si/length.h + include/units/isq/si/luminance.h + include/units/isq/si/luminous_intensity.h + include/units/isq/si/magnetic_flux.h + include/units/isq/si/magnetic_induction.h + include/units/isq/si/mass.h + include/units/isq/si/molar_energy.h + include/units/isq/si/momentum.h + include/units/isq/si/permeability.h + include/units/isq/si/permittivity.h + include/units/isq/si/power.h + include/units/isq/si/prefixes.h + include/units/isq/si/pressure.h + include/units/isq/si/radioactivity.h + include/units/isq/si/resistance.h + include/units/isq/si/si.h + include/units/isq/si/speed.h + include/units/isq/si/surface_tension.h + include/units/isq/si/thermal_conductivity.h + include/units/isq/si/thermodynamic_temperature.h + include/units/isq/si/time.h + include/units/isq/si/torque.h + include/units/isq/si/voltage.h + include/units/isq/si/volume.h +) diff --git a/src/systems/si/include/units/isq/si/absorbed_dose.h b/src/systems/si/include/units/isq/si/absorbed_dose.h index 965665e8..40159573 100644 --- a/src/systems/si/include/units/isq/si/absorbed_dose.h +++ b/src/systems/si/include/units/isq/si/absorbed_dose.h @@ -35,7 +35,7 @@ namespace units::isq::si { -struct gray : named_unit {}; +struct gray : named_unit {}; struct yoctogray : prefixed_unit {}; struct zeptogray : prefixed_unit {}; struct attogray : prefixed_unit {}; diff --git a/src/systems/si/include/units/isq/si/acceleration.h b/src/systems/si/include/units/isq/si/acceleration.h index 313c1df5..90f0168a 100644 --- a/src/systems/si/include/units/isq/si/acceleration.h +++ b/src/systems/si/include/units/isq/si/acceleration.h @@ -33,7 +33,7 @@ namespace units::isq::si { -struct metre_per_second_sq : unit {}; +struct metre_per_second_sq : derived_unit {}; struct dim_acceleration : isq::dim_acceleration {}; template U, Representation Rep = double> diff --git a/src/systems/si/include/units/isq/si/amount_of_substance.h b/src/systems/si/include/units/isq/si/amount_of_substance.h index e5d40c80..ba7578d8 100644 --- a/src/systems/si/include/units/isq/si/amount_of_substance.h +++ b/src/systems/si/include/units/isq/si/amount_of_substance.h @@ -34,7 +34,7 @@ namespace units::isq::si { -struct mole : named_unit {}; +struct mole : named_unit {}; struct dim_amount_of_substance : isq::dim_amount_of_substance {}; diff --git a/src/systems/si/include/units/isq/si/angular_velocity.h b/src/systems/si/include/units/isq/si/angular_velocity.h index fbb6e5c6..4c606798 100644 --- a/src/systems/si/include/units/isq/si/angular_velocity.h +++ b/src/systems/si/include/units/isq/si/angular_velocity.h @@ -29,12 +29,13 @@ // IWYU pragma: end_exports #include +#include #include #include namespace units::isq::si { -struct radian_per_second : named_unit {}; +struct radian_per_second : named_unit {}; struct dim_angular_velocity : isq::dim_angular_velocity, dim_time> {}; diff --git a/src/systems/si/include/units/isq/si/area.h b/src/systems/si/include/units/isq/si/area.h index 98bcb87c..d430a38c 100644 --- a/src/systems/si/include/units/isq/si/area.h +++ b/src/systems/si/include/units/isq/si/area.h @@ -34,31 +34,35 @@ namespace units::isq::si { -struct square_metre : unit {}; +struct square_metre : derived_unit {}; struct dim_area : isq::dim_area {}; -struct square_yoctometre : derived_unit {}; -struct square_zeptometre : derived_unit {}; -struct square_attometre : derived_unit {}; -struct square_femtometre : derived_unit {}; -struct square_picometre : derived_unit {}; -struct square_nanometre : derived_unit {}; -struct square_micrometre : derived_unit {}; -struct square_millimetre : derived_unit {}; -struct square_centimetre : derived_unit {}; -struct square_decimetre : derived_unit {}; -struct square_decametre : derived_unit {}; -struct square_hectometre : derived_unit {}; -struct square_kilometre : derived_unit {}; -struct square_megametre : derived_unit {}; -struct square_gigametre : derived_unit {}; -struct square_terametre : derived_unit {}; -struct square_petametre : derived_unit {}; -struct square_exametre : derived_unit {}; -struct square_zettametre : derived_unit {}; -struct square_yottametre : derived_unit {}; +struct square_yoctometre : derived_scaled_unit {}; +struct square_zeptometre : derived_scaled_unit {}; +struct square_attometre : derived_scaled_unit {}; +struct square_femtometre : derived_scaled_unit {}; +struct square_picometre : derived_scaled_unit {}; +struct square_nanometre : derived_scaled_unit {}; +struct square_micrometre : derived_scaled_unit {}; +struct square_millimetre : derived_scaled_unit {}; +struct square_centimetre : derived_scaled_unit {}; +struct square_decimetre : derived_scaled_unit {}; +struct square_decametre : derived_scaled_unit {}; +struct square_hectometre : derived_scaled_unit {}; +struct square_kilometre : derived_scaled_unit {}; +struct square_megametre : derived_scaled_unit {}; +struct square_gigametre : derived_scaled_unit {}; +struct square_terametre : derived_scaled_unit {}; +struct square_petametre : derived_scaled_unit {}; +struct square_exametre : derived_scaled_unit {}; +struct square_zettametre : derived_scaled_unit {}; +struct square_yottametre : derived_scaled_unit {}; -struct hectare : alias_unit {}; +struct are : alias_unit {}; +struct centiare : prefixed_alias_unit {}; +struct deciare : prefixed_unit {}; +struct decare : prefixed_unit {}; +struct hectare : prefixed_alias_unit {}; template U, Representation Rep = double> using area = quantity; @@ -235,6 +239,38 @@ constexpr auto operator"" _q_Ym2(unsigned long long l) } constexpr auto operator"" _q_Ym2(long double l) { return area(l); } +// a +constexpr auto operator"" _q_a(unsigned long long l) +{ + gsl_ExpectsAudit(std::in_range(l)); + return area(static_cast(l)); +} +constexpr auto operator"" _q_a(long double l) { return area(l); } + +// ca +constexpr auto operator"" _q_ca(unsigned long long l) +{ + gsl_ExpectsAudit(std::in_range(l)); + return area(static_cast(l)); +} +constexpr auto operator"" _q_ca(long double l) { return area(l); } + +// da +constexpr auto operator"" _q_da(unsigned long long l) +{ + gsl_ExpectsAudit(std::in_range(l)); + return area(static_cast(l)); +} +constexpr auto operator"" _q_da(long double l) { return area(l); } + +// daa +constexpr auto operator"" _q_daa(unsigned long long l) +{ + gsl_ExpectsAudit(std::in_range(l)); + return area(static_cast(l)); +} +constexpr auto operator"" _q_daa(long double l) { return area(l); } + // ha constexpr auto operator"" _q_ha(unsigned long long l) { @@ -273,6 +309,10 @@ inline constexpr auto Em2 = reference{}; inline constexpr auto Zm2 = reference{}; inline constexpr auto Ym2 = reference{}; +inline constexpr auto a = reference{}; +inline constexpr auto ca = reference{}; +inline constexpr auto da = reference{}; +inline constexpr auto daa = reference{}; inline constexpr auto ha = reference{}; } // namespace area_references diff --git a/src/systems/si/include/units/isq/si/capacitance.h b/src/systems/si/include/units/isq/si/capacitance.h index ddea6793..31a477f9 100644 --- a/src/systems/si/include/units/isq/si/capacitance.h +++ b/src/systems/si/include/units/isq/si/capacitance.h @@ -36,7 +36,7 @@ namespace units::isq::si { -struct farad : named_unit {}; +struct farad : named_unit {}; struct yoctofarad : prefixed_unit {}; struct zeptofarad : prefixed_unit {}; struct attofarad : prefixed_unit {}; diff --git a/src/systems/si/include/units/isq/si/catalytic_activity.h b/src/systems/si/include/units/isq/si/catalytic_activity.h index ad52a9d2..07ca426f 100644 --- a/src/systems/si/include/units/isq/si/catalytic_activity.h +++ b/src/systems/si/include/units/isq/si/catalytic_activity.h @@ -36,7 +36,7 @@ namespace units::isq::si { -struct katal : named_unit {}; +struct katal : named_unit {}; struct yoctokatal : prefixed_unit {}; struct zeptokatal : prefixed_unit {}; struct attokatal : prefixed_unit {}; @@ -58,7 +58,7 @@ struct exakatal : prefixed_unit {}; struct zettakatal : prefixed_unit {}; struct yottakatal : prefixed_unit {}; -struct enzyme_unit : named_scaled_unit(), katal> {}; +struct enzyme_unit : named_scaled_unit(), katal> {}; struct dim_catalytic_activity : isq::dim_catalytic_activity {}; diff --git a/src/systems/si/include/units/isq/si/charge_density.h b/src/systems/si/include/units/isq/si/charge_density.h index b50d0c03..52fba248 100644 --- a/src/systems/si/include/units/isq/si/charge_density.h +++ b/src/systems/si/include/units/isq/si/charge_density.h @@ -35,8 +35,8 @@ namespace units::isq::si { -struct coulomb_per_metre_cub : unit {}; -struct coulomb_per_metre_sq : unit {}; +struct coulomb_per_metre_cub : derived_unit {}; +struct coulomb_per_metre_sq : derived_unit {}; struct dim_charge_density : isq::dim_charge_density {}; diff --git a/src/systems/si/include/units/isq/si/concentration.h b/src/systems/si/include/units/isq/si/concentration.h index d59b3143..732583a5 100644 --- a/src/systems/si/include/units/isq/si/concentration.h +++ b/src/systems/si/include/units/isq/si/concentration.h @@ -34,7 +34,7 @@ namespace units::isq::si { -struct mol_per_metre_cub : unit {}; +struct mol_per_metre_cub : derived_unit {}; struct dim_concentration : isq::dim_concentration {}; diff --git a/src/systems/si/include/units/isq/si/conductance.h b/src/systems/si/include/units/isq/si/conductance.h index 36b8cc13..5442201f 100644 --- a/src/systems/si/include/units/isq/si/conductance.h +++ b/src/systems/si/include/units/isq/si/conductance.h @@ -35,7 +35,7 @@ namespace units::isq::si { -struct siemens : named_unit {}; +struct siemens : named_unit {}; struct yoctosiemens : prefixed_unit {}; struct zeptosiemens : prefixed_unit {}; struct attosiemens : prefixed_unit {}; diff --git a/src/systems/si/include/units/isq/si/current_density.h b/src/systems/si/include/units/isq/si/current_density.h index 4017414c..94234b5b 100644 --- a/src/systems/si/include/units/isq/si/current_density.h +++ b/src/systems/si/include/units/isq/si/current_density.h @@ -35,7 +35,7 @@ namespace units::isq::si { -struct ampere_per_metre_sq : unit {}; +struct ampere_per_metre_sq : derived_unit {}; struct dim_current_density : isq::dim_current_density {}; diff --git a/src/systems/si/include/units/isq/si/density.h b/src/systems/si/include/units/isq/si/density.h index 9a06b479..d890e225 100644 --- a/src/systems/si/include/units/isq/si/density.h +++ b/src/systems/si/include/units/isq/si/density.h @@ -35,7 +35,7 @@ namespace units::isq::si { -struct kilogram_per_metre_cub : unit {}; +struct kilogram_per_metre_cub : derived_unit {}; struct dim_density : isq::dim_density {}; diff --git a/src/systems/si/include/units/isq/si/dynamic_viscosity.h b/src/systems/si/include/units/isq/si/dynamic_viscosity.h index 763eb66c..81f0d2bb 100644 --- a/src/systems/si/include/units/isq/si/dynamic_viscosity.h +++ b/src/systems/si/include/units/isq/si/dynamic_viscosity.h @@ -34,7 +34,7 @@ namespace units::isq::si { -struct pascal_second : unit {}; +struct pascal_second : derived_unit {}; struct dim_dynamic_viscosity : isq::dim_dynamic_viscosity {}; diff --git a/src/systems/si/include/units/isq/si/electric_charge.h b/src/systems/si/include/units/isq/si/electric_charge.h index cb79b848..ca431827 100644 --- a/src/systems/si/include/units/isq/si/electric_charge.h +++ b/src/systems/si/include/units/isq/si/electric_charge.h @@ -35,7 +35,7 @@ namespace units::isq::si { -struct coulomb : named_unit {}; +struct coulomb : named_unit {}; struct dim_electric_charge : isq::dim_electric_charge {}; diff --git a/src/systems/si/include/units/isq/si/electric_current.h b/src/systems/si/include/units/isq/si/electric_current.h index 23c12021..740eb113 100644 --- a/src/systems/si/include/units/isq/si/electric_current.h +++ b/src/systems/si/include/units/isq/si/electric_current.h @@ -34,7 +34,7 @@ namespace units::isq::si { -struct ampere : named_unit {}; +struct ampere : named_unit {}; struct yoctoampere : prefixed_unit {}; struct zeptoampere : prefixed_unit {}; struct attoampere : prefixed_unit {}; diff --git a/src/systems/si/include/units/isq/si/electric_field_strength.h b/src/systems/si/include/units/isq/si/electric_field_strength.h index 49e843f7..773640d5 100644 --- a/src/systems/si/include/units/isq/si/electric_field_strength.h +++ b/src/systems/si/include/units/isq/si/electric_field_strength.h @@ -33,7 +33,7 @@ namespace units::isq::si { -struct volt_per_metre : unit {}; +struct volt_per_metre : derived_unit {}; struct dim_electric_field_strength : isq::dim_electric_field_strength {}; diff --git a/src/systems/si/include/units/isq/si/energy.h b/src/systems/si/include/units/isq/si/energy.h index 6efa1478..cf0eba26 100644 --- a/src/systems/si/include/units/isq/si/energy.h +++ b/src/systems/si/include/units/isq/si/energy.h @@ -35,7 +35,7 @@ namespace units::isq::si { -struct joule : named_unit {}; +struct joule : named_unit {}; struct yoctojoule : prefixed_unit {}; struct zeptojoule : prefixed_unit {}; struct attojoule : prefixed_unit {}; @@ -56,7 +56,7 @@ struct yottajoule : prefixed_unit {}; // N.B. electron charge (and eV) is an exact constant: // https://www.bipm.org/documents/20126/41483022/SI-Brochure-9.pdf#page=147 struct electronvolt : - named_scaled_unit(), joule> {}; + named_scaled_unit(), joule> {}; struct gigaelectronvolt : prefixed_unit {}; struct dim_energy : isq::dim_energy {}; diff --git a/src/systems/si/include/units/isq/si/energy_density.h b/src/systems/si/include/units/isq/si/energy_density.h index 3e4e501e..e9e156d7 100644 --- a/src/systems/si/include/units/isq/si/energy_density.h +++ b/src/systems/si/include/units/isq/si/energy_density.h @@ -34,7 +34,7 @@ namespace units::isq::si { -struct joule_per_metre_cub : unit {}; +struct joule_per_metre_cub : derived_unit {}; struct dim_energy_density : isq::dim_energy_density {}; template U, Representation Rep = double> diff --git a/src/systems/si/include/units/isq/si/force.h b/src/systems/si/include/units/isq/si/force.h index c0977aaf..fa2c1880 100644 --- a/src/systems/si/include/units/isq/si/force.h +++ b/src/systems/si/include/units/isq/si/force.h @@ -36,7 +36,7 @@ namespace units::isq::si { -struct newton : named_unit {}; +struct newton : named_unit {}; struct yoctonewton : prefixed_unit {}; struct zeptonewton : prefixed_unit {}; struct attonewton : prefixed_unit {}; diff --git a/src/systems/si/include/units/isq/si/frequency.h b/src/systems/si/include/units/isq/si/frequency.h index 0a9bd90a..39fa13ee 100644 --- a/src/systems/si/include/units/isq/si/frequency.h +++ b/src/systems/si/include/units/isq/si/frequency.h @@ -34,7 +34,7 @@ namespace units::isq::si { -struct hertz : named_unit {}; +struct hertz : named_unit {}; struct yoctohertz : prefixed_unit {}; struct zeptohertz : prefixed_unit {}; struct attohertz : prefixed_unit {}; diff --git a/src/systems/si/include/units/isq/si/heat_capacity.h b/src/systems/si/include/units/isq/si/heat_capacity.h index b264f59d..5ae30cfa 100644 --- a/src/systems/si/include/units/isq/si/heat_capacity.h +++ b/src/systems/si/include/units/isq/si/heat_capacity.h @@ -36,9 +36,9 @@ namespace units::isq::si { -struct joule_per_kelvin : unit {}; -struct joule_per_kilogram_kelvin : unit {}; -struct joule_per_mole_kelvin : unit {}; +struct joule_per_kelvin : derived_unit {}; +struct joule_per_kilogram_kelvin : derived_unit {}; +struct joule_per_mole_kelvin : derived_unit {}; struct dim_heat_capacity : isq::dim_heat_capacity {}; diff --git a/src/systems/si/include/units/isq/si/inductance.h b/src/systems/si/include/units/isq/si/inductance.h index e3eb6ee7..c6a14a98 100644 --- a/src/systems/si/include/units/isq/si/inductance.h +++ b/src/systems/si/include/units/isq/si/inductance.h @@ -35,7 +35,7 @@ namespace units::isq::si { -struct henry : named_unit {}; +struct henry : named_unit {}; struct yoctohenry : prefixed_unit {}; struct zeptohenry : prefixed_unit {}; diff --git a/src/systems/si/include/units/isq/si/length.h b/src/systems/si/include/units/isq/si/length.h index 582a9ae3..aefebdbb 100644 --- a/src/systems/si/include/units/isq/si/length.h +++ b/src/systems/si/include/units/isq/si/length.h @@ -34,7 +34,7 @@ namespace units::isq::si { -struct metre : named_unit {}; +struct metre : named_unit {}; struct yoctometre : prefixed_unit {}; struct zeptometre : prefixed_unit {}; struct attometre : prefixed_unit {}; @@ -56,8 +56,7 @@ struct exametre : prefixed_unit {}; struct zettametre : prefixed_unit {}; struct yottametre : prefixed_unit {}; -struct astronomical_unit : - named_scaled_unit(), metre> {}; +struct astronomical_unit : named_scaled_unit(), metre> {}; struct dim_length : isq::dim_length {}; diff --git a/src/systems/si/include/units/isq/si/luminance.h b/src/systems/si/include/units/isq/si/luminance.h index d6c6b74f..48f01073 100644 --- a/src/systems/si/include/units/isq/si/luminance.h +++ b/src/systems/si/include/units/isq/si/luminance.h @@ -34,7 +34,7 @@ namespace units::isq::si { -struct candela_per_metre_sq : unit {}; +struct candela_per_metre_sq : derived_unit {}; struct dim_luminance : isq::dim_luminance {}; template U, Representation Rep = double> diff --git a/src/systems/si/include/units/isq/si/luminous_intensity.h b/src/systems/si/include/units/isq/si/luminous_intensity.h index e4eff3c5..38e658f0 100644 --- a/src/systems/si/include/units/isq/si/luminous_intensity.h +++ b/src/systems/si/include/units/isq/si/luminous_intensity.h @@ -34,7 +34,7 @@ namespace units::isq::si { -struct candela : named_unit {}; +struct candela : named_unit {}; struct yoctocandela : prefixed_unit {}; struct zeptocandela : prefixed_unit {}; struct attocandela : prefixed_unit {}; diff --git a/src/systems/si/include/units/isq/si/magnetic_flux.h b/src/systems/si/include/units/isq/si/magnetic_flux.h index 57c1317d..77b1410c 100644 --- a/src/systems/si/include/units/isq/si/magnetic_flux.h +++ b/src/systems/si/include/units/isq/si/magnetic_flux.h @@ -35,7 +35,7 @@ namespace units::isq::si { -struct weber : named_unit {}; +struct weber : named_unit {}; struct yoctoweber : prefixed_unit {}; struct zeptoweber : prefixed_unit {}; diff --git a/src/systems/si/include/units/isq/si/magnetic_induction.h b/src/systems/si/include/units/isq/si/magnetic_induction.h index bdb33ef7..74bd7ca6 100644 --- a/src/systems/si/include/units/isq/si/magnetic_induction.h +++ b/src/systems/si/include/units/isq/si/magnetic_induction.h @@ -37,7 +37,7 @@ namespace units::isq::si { -struct tesla : named_unit {}; +struct tesla : named_unit {}; struct yoctotesla : prefixed_unit {}; struct zeptotesla : prefixed_unit {}; @@ -56,7 +56,7 @@ struct exatesla : prefixed_unit {}; struct zettatesla : prefixed_unit {}; struct yottatesla : prefixed_unit {}; -struct gauss : named_scaled_unit(), tesla> {}; +struct gauss : named_scaled_unit(), tesla> {}; struct dim_magnetic_induction : isq::dim_magnetic_induction {}; diff --git a/src/systems/si/include/units/isq/si/mass.h b/src/systems/si/include/units/isq/si/mass.h index d9d7fdf7..53a574f4 100644 --- a/src/systems/si/include/units/isq/si/mass.h +++ b/src/systems/si/include/units/isq/si/mass.h @@ -34,7 +34,7 @@ namespace units::isq::si { -struct gram : named_unit {}; +struct gram : named_unit {}; struct yoctogram : prefixed_unit {}; struct zeptogram : prefixed_unit {}; struct attogram : prefixed_unit {}; @@ -56,7 +56,7 @@ struct exagram : prefixed_unit {}; struct zettagram : prefixed_unit {}; struct yottagram : prefixed_unit {}; -struct tonne : alias_unit {}; +struct tonne : alias_unit {}; struct yoctotonne : prefixed_alias_unit {}; struct zeptotonne : prefixed_alias_unit {}; struct attotonne : prefixed_alias_unit {}; @@ -79,8 +79,7 @@ struct zettatonne : prefixed_unit {}; struct yottatonne : prefixed_unit {}; struct dalton : - named_scaled_unit(), - kilogram> {}; + named_scaled_unit(), kilogram> {}; struct dim_mass : isq::dim_mass {}; diff --git a/src/systems/si/include/units/isq/si/molar_energy.h b/src/systems/si/include/units/isq/si/molar_energy.h index fa4cae49..02cb9072 100644 --- a/src/systems/si/include/units/isq/si/molar_energy.h +++ b/src/systems/si/include/units/isq/si/molar_energy.h @@ -35,7 +35,7 @@ namespace units::isq::si { -struct joule_per_mole : unit {}; +struct joule_per_mole : derived_unit {}; struct dim_molar_energy : isq::dim_molar_energy {}; diff --git a/src/systems/si/include/units/isq/si/momentum.h b/src/systems/si/include/units/isq/si/momentum.h index f4605e88..46446c92 100644 --- a/src/systems/si/include/units/isq/si/momentum.h +++ b/src/systems/si/include/units/isq/si/momentum.h @@ -34,7 +34,7 @@ namespace units::isq::si { -struct kilogram_metre_per_second : unit {}; +struct kilogram_metre_per_second : derived_unit {}; struct dim_momentum : isq::dim_momentum {}; template U, Representation Rep = double> diff --git a/src/systems/si/include/units/isq/si/permeability.h b/src/systems/si/include/units/isq/si/permeability.h index 2cb04734..5b961b21 100644 --- a/src/systems/si/include/units/isq/si/permeability.h +++ b/src/systems/si/include/units/isq/si/permeability.h @@ -34,7 +34,7 @@ namespace units::isq::si { -struct henry_per_metre : unit {}; +struct henry_per_metre : derived_unit {}; struct dim_permeability : isq::dim_permeability {}; diff --git a/src/systems/si/include/units/isq/si/permittivity.h b/src/systems/si/include/units/isq/si/permittivity.h index bb6b1953..cd99be6c 100644 --- a/src/systems/si/include/units/isq/si/permittivity.h +++ b/src/systems/si/include/units/isq/si/permittivity.h @@ -34,7 +34,7 @@ namespace units::isq::si { -struct farad_per_metre : unit {}; +struct farad_per_metre : derived_unit {}; struct dim_permittivity : isq::dim_permittivity {}; diff --git a/src/systems/si/include/units/isq/si/power.h b/src/systems/si/include/units/isq/si/power.h index 360e92e9..d95d5c30 100644 --- a/src/systems/si/include/units/isq/si/power.h +++ b/src/systems/si/include/units/isq/si/power.h @@ -35,7 +35,7 @@ namespace units::isq::si { -struct watt : named_unit {}; +struct watt : named_unit {}; struct yoctowatt : prefixed_unit {}; struct zeptowatt : prefixed_unit {}; struct attowatt : prefixed_unit {}; diff --git a/src/systems/si/include/units/isq/si/prefixes.h b/src/systems/si/include/units/isq/si/prefixes.h index a6e9cd08..0efabcf3 100644 --- a/src/systems/si/include/units/isq/si/prefixes.h +++ b/src/systems/si/include/units/isq/si/prefixes.h @@ -26,29 +26,27 @@ namespace units::isq::si { -struct prefix : prefix_family {}; - // clang-format off -struct yocto : units::prefix {}; -struct zepto : units::prefix {}; -struct atto : units::prefix {}; -struct femto : units::prefix {}; -struct pico : units::prefix {}; -struct nano : units::prefix {}; -struct micro : units::prefix {}; -struct milli : units::prefix {}; -struct centi : units::prefix {}; -struct deci : units::prefix {}; -struct deca : units::prefix {}; -struct hecto : units::prefix {}; -struct kilo : units::prefix {}; -struct mega : units::prefix {}; -struct giga : units::prefix {}; -struct tera : units::prefix {}; -struct peta : units::prefix {}; -struct exa : units::prefix {}; -struct zetta : units::prefix {}; -struct yotta : units::prefix {}; +struct yocto : units::prefix {}; +struct zepto : units::prefix {}; +struct atto : units::prefix {}; +struct femto : units::prefix {}; +struct pico : units::prefix {}; +struct nano : units::prefix {}; +struct micro : units::prefix {}; +struct milli : units::prefix {}; +struct centi : units::prefix {}; +struct deci : units::prefix {}; +struct deca : units::prefix {}; +struct hecto : units::prefix {}; +struct kilo : units::prefix {}; +struct mega : units::prefix {}; +struct giga : units::prefix {}; +struct tera : units::prefix {}; +struct peta : units::prefix {}; +struct exa : units::prefix {}; +struct zetta : units::prefix {}; +struct yotta : units::prefix {}; // clang-format on } // namespace units::isq::si diff --git a/src/systems/si/include/units/isq/si/pressure.h b/src/systems/si/include/units/isq/si/pressure.h index b3c94279..86bed5d2 100644 --- a/src/systems/si/include/units/isq/si/pressure.h +++ b/src/systems/si/include/units/isq/si/pressure.h @@ -36,7 +36,7 @@ namespace units::isq::si { -struct pascal : named_unit {}; +struct pascal : named_unit {}; struct yoctopascal : prefixed_unit {}; struct zeptopascal : prefixed_unit {}; struct attopascal : prefixed_unit {}; diff --git a/src/systems/si/include/units/isq/si/radioactivity.h b/src/systems/si/include/units/isq/si/radioactivity.h index 017d8fcf..d46c81e4 100644 --- a/src/systems/si/include/units/isq/si/radioactivity.h +++ b/src/systems/si/include/units/isq/si/radioactivity.h @@ -34,7 +34,7 @@ namespace units::isq::si { -struct becquerel : named_unit {}; +struct becquerel : named_unit {}; struct yoctobecquerel : prefixed_unit {}; struct zeptobecquerel : prefixed_unit {}; struct attobecquerel : prefixed_unit {}; @@ -280,47 +280,47 @@ using namespace radioactivity_references; namespace units::aliases::isq::si::inline radioactivity { template -using Bq = units::isq::radioactivity; +using Bq = units::isq::si::radioactivity; template -using yBq = units::isq::radioactivity; +using yBq = units::isq::si::radioactivity; template -using zBq = units::isq::radioactivity; +using zBq = units::isq::si::radioactivity; template -using aBq = units::isq::radioactivity; +using aBq = units::isq::si::radioactivity; template -using fBq = units::isq::radioactivity; +using fBq = units::isq::si::radioactivity; template -using pBq = units::isq::radioactivity; +using pBq = units::isq::si::radioactivity; template -using nBq = units::isq::radioactivity; +using nBq = units::isq::si::radioactivity; template -using uBq = units::isq::radioactivity; +using uBq = units::isq::si::radioactivity; template -using mBq = units::isq::radioactivity; +using mBq = units::isq::si::radioactivity; template -using cBq = units::isq::radioactivity; +using cBq = units::isq::si::radioactivity; template -using dBq = units::isq::radioactivity; +using dBq = units::isq::si::radioactivity; template -using daBq = units::isq::radioactivity; +using daBq = units::isq::si::radioactivity; template -using hBq = units::isq::radioactivity; +using hBq = units::isq::si::radioactivity; template -using kBq = units::isq::radioactivity; +using kBq = units::isq::si::radioactivity; template -using MBq = units::isq::radioactivity; +using MBq = units::isq::si::radioactivity; template -using GBq = units::isq::radioactivity; +using GBq = units::isq::si::radioactivity; template -using TBq = units::isq::radioactivity; +using TBq = units::isq::si::radioactivity; template -using PBq = units::isq::radioactivity; +using PBq = units::isq::si::radioactivity; template -using EBq = units::isq::radioactivity; +using EBq = units::isq::si::radioactivity; template -using ZBq = units::isq::radioactivity; +using ZBq = units::isq::si::radioactivity; template -using YBq = units::isq::radioactivity; +using YBq = units::isq::si::radioactivity; } // namespace units::aliases::isq::si::inline radioactivity diff --git a/src/systems/si/include/units/isq/si/resistance.h b/src/systems/si/include/units/isq/si/resistance.h index 83d3fca0..ea57ed61 100644 --- a/src/systems/si/include/units/isq/si/resistance.h +++ b/src/systems/si/include/units/isq/si/resistance.h @@ -36,7 +36,7 @@ namespace units::isq::si { -struct ohm : named_unit {}; +struct ohm : named_unit {}; struct yoctoohm : prefixed_unit {}; struct zeptoohm : prefixed_unit {}; struct attoohm : prefixed_unit {}; diff --git a/src/systems/si/include/units/isq/si/speed.h b/src/systems/si/include/units/isq/si/speed.h index 4d03d36b..8bcc17b7 100644 --- a/src/systems/si/include/units/isq/si/speed.h +++ b/src/systems/si/include/units/isq/si/speed.h @@ -34,10 +34,10 @@ namespace units::isq::si { -struct metre_per_second : unit {}; +struct metre_per_second : derived_unit {}; struct dim_speed : isq::dim_speed {}; -struct kilometre_per_hour : derived_unit {}; +struct kilometre_per_hour : derived_scaled_unit {}; template U, Representation Rep = double> using speed = quantity; diff --git a/src/systems/si/include/units/isq/si/surface_tension.h b/src/systems/si/include/units/isq/si/surface_tension.h index 87b02a2c..382b133f 100644 --- a/src/systems/si/include/units/isq/si/surface_tension.h +++ b/src/systems/si/include/units/isq/si/surface_tension.h @@ -33,7 +33,7 @@ namespace units::isq::si { -struct newton_per_metre : unit {}; +struct newton_per_metre : derived_unit {}; struct dim_surface_tension : isq::dim_surface_tension {}; diff --git a/src/systems/si/include/units/isq/si/thermal_conductivity.h b/src/systems/si/include/units/isq/si/thermal_conductivity.h index d4a09c9f..64177b52 100644 --- a/src/systems/si/include/units/isq/si/thermal_conductivity.h +++ b/src/systems/si/include/units/isq/si/thermal_conductivity.h @@ -34,7 +34,7 @@ namespace units::isq::si { -struct watt_per_metre_kelvin : unit {}; +struct watt_per_metre_kelvin : derived_unit {}; struct dim_thermal_conductivity : isq::dim_thermal_conductivity // IWYU pragma: end_exports +#include #include namespace units::isq::si { -struct kelvin : named_unit {}; +struct kelvin : named_unit {}; struct dim_thermodynamic_temperature : isq::dim_thermodynamic_temperature {}; diff --git a/src/systems/si/include/units/isq/si/time.h b/src/systems/si/include/units/isq/si/time.h index 34d7c025..17f47804 100644 --- a/src/systems/si/include/units/isq/si/time.h +++ b/src/systems/si/include/units/isq/si/time.h @@ -34,7 +34,7 @@ namespace units::isq::si { -struct second : named_unit {}; +struct second : named_unit {}; struct yoctosecond : prefixed_unit {}; struct zeptosecond : prefixed_unit {}; struct attosecond : prefixed_unit {}; @@ -43,9 +43,9 @@ struct picosecond : prefixed_unit {}; struct nanosecond : prefixed_unit {}; struct microsecond : prefixed_unit {}; struct millisecond : prefixed_unit {}; -struct minute : named_scaled_unit(), second> {}; -struct hour : named_scaled_unit(), minute> {}; -struct day : named_scaled_unit(), hour> {}; +struct minute : named_scaled_unit(), second> {}; +struct hour : named_scaled_unit(), minute> {}; +struct day : named_scaled_unit(), hour> {}; struct dim_time : isq::dim_time {}; diff --git a/src/systems/si/include/units/isq/si/torque.h b/src/systems/si/include/units/isq/si/torque.h index 1245cf6c..14e5aec2 100644 --- a/src/systems/si/include/units/isq/si/torque.h +++ b/src/systems/si/include/units/isq/si/torque.h @@ -35,7 +35,7 @@ namespace units::isq::si { -struct newton_metre_per_radian : unit {}; +struct newton_metre_per_radian : derived_unit {}; struct dim_torque : isq::dim_torque> {}; diff --git a/src/systems/si/include/units/isq/si/voltage.h b/src/systems/si/include/units/isq/si/voltage.h index 31922688..e06cc1be 100644 --- a/src/systems/si/include/units/isq/si/voltage.h +++ b/src/systems/si/include/units/isq/si/voltage.h @@ -36,7 +36,7 @@ namespace units::isq::si { -struct volt : named_unit {}; +struct volt : named_unit {}; struct yoctovolt : prefixed_unit {}; struct zeptovolt : prefixed_unit {}; struct attovolt : prefixed_unit {}; diff --git a/src/systems/si/include/units/isq/si/volume.h b/src/systems/si/include/units/isq/si/volume.h index 8430e60b..1f61d874 100644 --- a/src/systems/si/include/units/isq/si/volume.h +++ b/src/systems/si/include/units/isq/si/volume.h @@ -34,31 +34,31 @@ namespace units::isq::si { -struct cubic_metre : unit {}; +struct cubic_metre : derived_unit {}; struct dim_volume : isq::dim_volume {}; -struct cubic_yoctometre : derived_unit {}; -struct cubic_zeptometre : derived_unit {}; -struct cubic_attometre : derived_unit {}; -struct cubic_femtometre : derived_unit {}; -struct cubic_picometre : derived_unit {}; -struct cubic_nanometre : derived_unit {}; -struct cubic_micrometre : derived_unit {}; -struct cubic_millimetre : derived_unit {}; -struct cubic_centimetre : derived_unit {}; -struct cubic_decimetre : derived_unit {}; -struct cubic_decametre : derived_unit {}; -struct cubic_hectometre : derived_unit {}; -struct cubic_kilometre : derived_unit {}; -struct cubic_megametre : derived_unit {}; -struct cubic_gigametre : derived_unit {}; -struct cubic_terametre : derived_unit {}; -struct cubic_petametre : derived_unit {}; -struct cubic_exametre : derived_unit {}; -struct cubic_zettametre : derived_unit {}; -struct cubic_yottametre : derived_unit {}; +struct cubic_yoctometre : derived_scaled_unit {}; +struct cubic_zeptometre : derived_scaled_unit {}; +struct cubic_attometre : derived_scaled_unit {}; +struct cubic_femtometre : derived_scaled_unit {}; +struct cubic_picometre : derived_scaled_unit {}; +struct cubic_nanometre : derived_scaled_unit {}; +struct cubic_micrometre : derived_scaled_unit {}; +struct cubic_millimetre : derived_scaled_unit {}; +struct cubic_centimetre : derived_scaled_unit {}; +struct cubic_decimetre : derived_scaled_unit {}; +struct cubic_decametre : derived_scaled_unit {}; +struct cubic_hectometre : derived_scaled_unit {}; +struct cubic_kilometre : derived_scaled_unit {}; +struct cubic_megametre : derived_scaled_unit {}; +struct cubic_gigametre : derived_scaled_unit {}; +struct cubic_terametre : derived_scaled_unit {}; +struct cubic_petametre : derived_scaled_unit {}; +struct cubic_exametre : derived_scaled_unit {}; +struct cubic_zettametre : derived_scaled_unit {}; +struct cubic_yottametre : derived_scaled_unit {}; -struct litre : alias_unit {}; +struct litre : alias_unit {}; struct yoctolitre : prefixed_alias_unit {}; struct zeptolitre : prefixed_unit {}; struct attolitre : prefixed_unit {}; diff --git a/test/unit_test/runtime/fmt_test.cpp b/test/unit_test/runtime/fmt_test.cpp index 3ec5211e..3f729638 100644 --- a/test/unit_test/runtime/fmt_test.cpp +++ b/test/unit_test/runtime/fmt_test.cpp @@ -189,7 +189,7 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]") SECTION("surface tension") { struct newton_per_centimetre : - derived_unit {}; + derived_scaled_unit {}; const surface_tension q(123); os << q; diff --git a/test/unit_test/runtime/fmt_units_test.cpp b/test/unit_test/runtime/fmt_units_test.cpp index 58531174..22c04fe2 100644 --- a/test/unit_test/runtime/fmt_units_test.cpp +++ b/test/unit_test/runtime/fmt_units_test.cpp @@ -66,7 +66,7 @@ TEST_CASE("std::format on synthesized unit symbols", "[text][fmt]") CHECK(STD_FMT::format("{}", 1_q_fathom_us) == "1 fathom(us)"); CHECK(STD_FMT::format("{}", 1_q_mi) == "1 mi"); CHECK(STD_FMT::format("{}", 1_q_mi_us) == "1 mi(us)"); - CHECK(STD_FMT::format("{}", 1_q_naut_mi) == "1 mi(naut)"); + CHECK(STD_FMT::format("{}", 1_q_naut_mi) == "1 nmi"); CHECK(STD_FMT::format("{}", 1_q_ch) == "1 ch"); CHECK(STD_FMT::format("{}", 1_q_rd) == "1 rd"); CHECK(STD_FMT::format("{}", 1_q_thou) == "1 thou"); diff --git a/test/unit_test/static/chrono_test.cpp b/test/unit_test/static/chrono_test.cpp index 348ec3ba..952ce1fa 100644 --- a/test/unit_test/static/chrono_test.cpp +++ b/test/unit_test/static/chrono_test.cpp @@ -20,6 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +#include "test_tools.h" #include #include #include @@ -82,12 +83,12 @@ static_assert(!std::convertible_to>); -static_assert(is_same_v>); -static_assert(is_same_v>); -static_assert(is_same_v>); +static_assert(compare>); +static_assert(compare>); +static_assert(compare>); +static_assert(compare>); // operators static_assert(quantity{1s} + 1_q_s == 2_q_s); diff --git a/test/unit_test/static/concepts_test.cpp b/test/unit_test/static/concepts_test.cpp index a97a1e13..2e9d66d1 100644 --- a/test/unit_test/static/concepts_test.cpp +++ b/test/unit_test/static/concepts_test.cpp @@ -42,15 +42,9 @@ namespace { using namespace units; using namespace units::isq; -// Prefix family - -static_assert(PrefixFamily); -static_assert(!PrefixFamily); - // Prefix static_assert(Prefix); -static_assert(!Prefix); static_assert(!Prefix); // BaseDimension @@ -83,6 +77,13 @@ static_assert(!Unit); static_assert(!Unit); static_assert(!Unit); +// NamedUnit + +static_assert(NamedUnit); +static_assert(NamedUnit); +static_assert(NamedUnit); +static_assert(!NamedUnit); + // UnitOf static_assert(UnitOf); diff --git a/test/unit_test/static/custom_unit_test.cpp b/test/unit_test/static/custom_unit_test.cpp index 9ea04d20..474249fb 100644 --- a/test/unit_test/static/custom_unit_test.cpp +++ b/test/unit_test/static/custom_unit_test.cpp @@ -36,7 +36,7 @@ using namespace units; using namespace units::isq::si; // power spectral density -struct sq_volt_per_hertz : unit {}; +struct sq_volt_per_hertz : derived_unit {}; struct dim_power_spectral_density : derived_dimension, units::exponent> {}; @@ -45,7 +45,7 @@ template U, Representation Rep = double> using power_spectral_density = quantity; // amplitude spectral density -struct volt_per_sqrt_hertz : unit {}; +struct volt_per_sqrt_hertz : derived_unit {}; struct dim_amplitude_spectral_density : derived_dimension, units::exponent> {}; @@ -69,11 +69,11 @@ static_assert(compare(16 namespace { -struct kilogram_per_second : unit {}; +struct kilogram_per_second : derived_unit {}; struct dim_mass_rate : derived_dimension, units::exponent> { }; -struct kilogram_per_hour : derived_unit {}; +struct kilogram_per_hour : derived_scaled_unit {}; [[maybe_unused]] constexpr auto a = 1_q_kg / 1_q_h; } // namespace diff --git a/test/unit_test/static/dimension_op_test.cpp b/test/unit_test/static/dimension_op_test.cpp index 61de01f9..fe1561cb 100644 --- a/test/unit_test/static/dimension_op_test.cpp +++ b/test/unit_test/static/dimension_op_test.cpp @@ -30,13 +30,13 @@ using namespace units; namespace { -struct u0 : named_unit {}; +struct u0 : named_unit {}; struct d0 : base_dimension<"d0", u0> {}; -struct u1 : named_unit {}; +struct u1 : named_unit {}; struct d1 : base_dimension<"d1", u1> {}; -struct u2 : named_unit {}; +struct u2 : named_unit {}; struct d2 : base_dimension<"d2", u2> {}; -struct u3 : named_unit {}; +struct u3 : named_unit {}; struct d3 : base_dimension<"d3", u3> {}; // exponent_invert diff --git a/test/unit_test/static/kind_test.cpp b/test/unit_test/static/kind_test.cpp index 3e9b4eb8..0c79059c 100644 --- a/test/unit_test/static/kind_test.cpp +++ b/test/unit_test/static/kind_test.cpp @@ -20,6 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +#include "test_tools.h" #include #include #include @@ -62,7 +63,7 @@ static_assert(!PointKind); static_assert(is_same_v); static_assert(is_same_v); -static_assert(is_same_v, downcast_kind>); +static_assert(compare, downcast_kind>); static_assert(equivalent); static_assert(equivalent); @@ -124,7 +125,7 @@ static_assert(PointKind); static_assert(is_same_v); static_assert(is_same_v); -static_assert(is_same_v, downcast_point_kind>); +static_assert(compare, downcast_point_kind>); static_assert(equivalent); static_assert(equivalent); @@ -162,8 +163,8 @@ static_assert(!PointKind); static_assert(is_same_v); static_assert(is_same_v); -static_assert(is_same_v, downcast_kind>); -static_assert(is_same_v, downcast_kind>); +static_assert(compare, downcast_kind>); +static_assert(compare, downcast_kind>); static_assert(equivalent); static_assert(equivalent); @@ -181,7 +182,7 @@ static_assert(PointKind); static_assert(is_same_v); static_assert(is_same_v); -static_assert(is_same_v, downcast_point_kind>); +static_assert(compare, downcast_point_kind>); static_assert(equivalent); static_assert(equivalent); @@ -200,6 +201,6 @@ static_assert(!equivalent); static_assert(!equivalent); -static_assert(is_same_v, downcast_kind>); +static_assert(compare, downcast_kind>); } // namespace diff --git a/test/unit_test/static/quantity_kind_test.cpp b/test/unit_test/static/quantity_kind_test.cpp index f7d4f642..de507037 100644 --- a/test/unit_test/static/quantity_kind_test.cpp +++ b/test/unit_test/static/quantity_kind_test.cpp @@ -481,11 +481,11 @@ static_assert(invalid_compound_assignments_(2 * m) + width(3 * m), width(5 * m))); static_assert(same(width(2 * m) + width(3. * m), width(5. * m))); static_assert(same(width(2. * m) + width(3 * m), width(5. * m))); -static_assert(same(width(2 * km) + width(3e3 * m), width(5e3 * m))); +static_assert(comp(width(2 * km) + width(3e3 * m), width(5e3 * m))); static_assert(same(width(2 * m) - width(3 * m), width(-1 * m))); static_assert(same(width(2 * m) - width(3. * m), width(-1. * m))); static_assert(same(width(2. * m) - width(3 * m), width(-1. * m))); -static_assert(same(width(2e3 * m) - width(3 * km), width(-1e3 * m))); +static_assert(comp(width(2e3 * m) - width(3 * km), width(-1e3 * m))); static_assert( is_same_v(0 * m) + width(0 * m)).common().number()), @@ -531,131 +531,131 @@ static_assert(same(2 * width(3 * m), width(6 * m))); static_assert(same(2 * width(3. * m), width(6. * m))); static_assert(same(2. * width(3 * m), width(6. * m))); -static_assert(same(width(2 * m) * quantity(3), width(6 * m))); -static_assert(same(width(2 * m) * quantity(3.), width(6. * m))); -static_assert(same(width(2. * m) * quantity(3), width(6. * m))); -static_assert(same(quantity(2) * width(3 * m), width(6 * m))); -static_assert(same(quantity(2) * width(3. * m), width(6. * m))); -static_assert(same(quantity(2.) * width(3 * m), width(6. * m))); +static_assert(comp(width(2 * m) * quantity(3), width(6 * m))); +static_assert(comp(width(2 * m) * quantity(3.), width(6. * m))); +static_assert(comp(width(2. * m) * quantity(3), width(6. * m))); +static_assert(comp(quantity(2) * width(3 * m), width(6 * m))); +static_assert(comp(quantity(2) * width(3. * m), width(6. * m))); +static_assert(comp(quantity(2.) * width(3 * m), width(6. * m))); -static_assert(same(width(2 * m) * quantity_kind, one, int>(3), +static_assert(comp(width(2 * m) * quantity_kind, one, int>(3), width(6 * m))); -static_assert(same(width(2 * m) * quantity_kind, one, double>(3.), +static_assert(comp(width(2 * m) * quantity_kind, one, double>(3.), width(6. * m))); -static_assert(same(width(2. * m) * quantity_kind, one, int>(3), +static_assert(comp(width(2. * m) * quantity_kind, one, int>(3), width(6. * m))); -static_assert(same(quantity_kind, one, int>(2) * width(3 * m), +static_assert(comp(quantity_kind, one, int>(2) * width(3 * m), width(6 * m))); -static_assert(same(quantity_kind, one, int>(2) * width(3. * m), +static_assert(comp(quantity_kind, one, int>(2) * width(3. * m), width(6. * m))); -static_assert(same(quantity_kind, one, double>(2.) * width(3 * m), +static_assert(comp(quantity_kind, one, double>(2.) * width(3 * m), width(6. * m))); -static_assert(same(height(2 * m) * (3 * Hz), rate_of_climb(6 * (m / s)))); -static_assert(same(height(2 * m) * (3. * Hz), rate_of_climb(6. * (m / s)))); -static_assert(same(height(2. * m) * (3 * Hz), rate_of_climb(6. * (m / s)))); -static_assert(same((2 * Hz) * height(3 * m), rate_of_climb(6 * (m / s)))); -static_assert(same((2 * Hz) * height(3. * m), rate_of_climb(6. * (m / s)))); -static_assert(same((2. * Hz) * height(3 * m), rate_of_climb(6. * (m / s)))); +static_assert(comp(height(2 * m) * (3 * Hz), rate_of_climb(6 * (m / s)))); +static_assert(comp(height(2 * m) * (3. * Hz), rate_of_climb(6. * (m / s)))); +static_assert(comp(height(2. * m) * (3 * Hz), rate_of_climb(6. * (m / s)))); +static_assert(comp((2 * Hz) * height(3 * m), rate_of_climb(6 * (m / s)))); +static_assert(comp((2 * Hz) * height(3. * m), rate_of_climb(6. * (m / s)))); +static_assert(comp((2. * Hz) * height(3 * m), rate_of_climb(6. * (m / s)))); -static_assert(same(quantity_kind(2 * s) * (3 * Hz), +static_assert(comp(quantity_kind(2 * s) * (3 * Hz), quantity_kind, one, int>(6))); -static_assert(same((3 * Hz) * quantity_kind(2 * s), +static_assert(comp((3 * Hz) * quantity_kind(2 * s), quantity_kind, one, int>(6))); -static_assert(same(apples(2) * quantity(2), apples(4))); -static_assert(same(quantity(2) * apples(2), apples(4))); +static_assert(comp(apples(2) * quantity(2), apples(4))); +static_assert(comp(quantity(2) * apples(2), apples(4))); // clang-format off -static_assert(same(width(4 * m) * (1 * m), horizontal_area(4 * (m * m)))); -static_assert(same(width(2 * m) * width(2 * m), horizontal_area(4 * (m * m)))); -static_assert(same(width(2 * m) * width(2 * m), horizontal_area(4 * (m * m)))); -static_assert(same(width(2 * m) * width(2 * m), horizontal_area(4 * (m * m)))); +static_assert(comp(width(4 * m) * (1 * m), horizontal_area(4 * (m * m)))); +static_assert(comp(width(2 * m) * width(2 * m), horizontal_area(4 * (m * m)))); +static_assert(comp(width(2 * m) * width(2 * m), horizontal_area(4 * (m * m)))); +static_assert(comp(width(2 * m) * width(2 * m), horizontal_area(4 * (m * m)))); // clang-format on -static_assert(same(apples(2) * apples(2), apples(4))); -static_assert(same(apples(2) * (2 / apples(1)), apples(4))); +static_assert(comp(apples(2) * apples(2), apples(4))); +static_assert(comp(apples(2) * (2 / apples(1)), apples(4))); -static_assert(same(width(4 * m) * (1 * mm), horizontal_area(4 * (m * mm)))); -static_assert(same(width(2 * m) * width(2 * m), horizontal_area(4 * (m * m)))); -static_assert(same(width(2 * m) * (1 / width(2 * m)), +static_assert(comp(width(4 * m) * (1 * mm), horizontal_area(4 * (m * mm)))); +static_assert(comp(width(2 * m) * width(2 * m), horizontal_area(4 * (m * m)))); +static_assert(comp(width(2 * m) * (1 / width(2 * m)), quantity_kind, one>(1))); static_assert(same(width(2 * m) / 3, width(0 * m))); static_assert(same(width(2 * m) / 3., width(2 / 3. * m))); static_assert(same(width(2. * m) / 3, width(2. / 3 * m))); -static_assert(same(width(2 * m) / quantity(3), width(0 * m))); -static_assert(same(width(2 * m) / quantity(3.), width(2 / 3. * m))); -static_assert(same(width(2. * m) / quantity(3), width(2. / 3 * m))); +static_assert(comp(width(2 * m) / quantity(3), width(0 * m))); +static_assert(comp(width(2 * m) / quantity(3.), width(2 / 3. * m))); +static_assert(comp(width(2. * m) / quantity(3), width(2. / 3 * m))); -static_assert(same(width(2 * m) / quantity_kind, one, int>(3), +static_assert(comp(width(2 * m) / quantity_kind, one, int>(3), width(0 * m))); -static_assert(same(width(2 * m) / quantity_kind, one, double>(3.), +static_assert(comp(width(2 * m) / quantity_kind, one, double>(3.), width(2 / 3. * m))); -static_assert(same(width(2. * m) / quantity_kind, one, double>(3), +static_assert(comp(width(2. * m) / quantity_kind, one, double>(3), width(2. / 3 * m))); -static_assert(same(2 / quantity_kind(3 * s), +static_assert(comp(2 / quantity_kind(3 * s), quantity_kind, hertz, int>(2 / 3 / (1 * s)))); -static_assert(same(2 / quantity_kind(3. * s), +static_assert(comp(2 / quantity_kind(3. * s), quantity_kind, hertz, double>(2 / 3. / (1 * s)))); -static_assert(same(2. / quantity_kind(3 * s), +static_assert(comp(2. / quantity_kind(3 * s), quantity_kind, hertz, double>(2 / 3. / (1 * s)))); -static_assert(same(quantity(2) / quantity_kind(3 * s), +static_assert(comp(quantity(2) / quantity_kind(3 * s), quantity_kind, hertz, int>(2 / 3 / (1 * s)))); -static_assert(same(quantity(2) / quantity_kind(3. * s), +static_assert(comp(quantity(2) / quantity_kind(3. * s), quantity_kind, hertz, double>(2 / 3. / (1 * s)))); -static_assert(same(quantity(2.) / quantity_kind(3 * s), +static_assert(comp(quantity(2.) / quantity_kind(3 * s), quantity_kind, hertz, double>(2 / 3. / (1 * s)))); -static_assert(same(quantity_kind, one, int>(2) / +static_assert(comp(quantity_kind, one, int>(2) / quantity_kind(3 * s), quantity_kind, hertz, int>(2 / 3 / (1 * s)))); -static_assert(same(quantity_kind, one, int>(2) / +static_assert(comp(quantity_kind, one, int>(2) / quantity_kind(3. * s), quantity_kind, hertz, double>(2 / 3. / (1 * s)))); -static_assert(same(quantity_kind, one, double>(2.) / +static_assert(comp(quantity_kind, one, double>(2.) / quantity_kind(3 * s), quantity_kind, hertz, double>(2 / 3. / (1 * s)))); -static_assert(same(height(2 * m) / (3 * s), rate_of_climb(0 * (m / s)))); -static_assert(same(height(2 * m) / (3. * s), rate_of_climb(2 / 3. * (m / s)))); -static_assert(same(height(2. * m) / (3 * s), rate_of_climb(2. / 3 * (m / s)))); +static_assert(comp(height(2 * m) / (3 * s), rate_of_climb(0 * (m / s)))); +static_assert(comp(height(2 * m) / (3. * s), rate_of_climb(2 / 3. * (m / s)))); +static_assert(comp(height(2. * m) / (3 * s), rate_of_climb(2. / 3 * (m / s)))); -static_assert(same(width(2 * m) * dimensionless(3), width(6 * cm))); -static_assert(same(dimensionless(2) * width(3 * m), width(6 * cm))); -static_assert(same(width(2 * m) / dimensionless(3), +static_assert(comp(width(2 * m) * dimensionless(3), width(6 * cm))); +static_assert(comp(dimensionless(2) * width(3 * m), width(6 * cm))); +static_assert(comp(width(2 * m) / dimensionless(3), width(2. / 3 * hm))); static_assert(same(width(2 * m) % dimensionless(3), width(2 * m))); -static_assert(same(height(2 * m) / (3 * m), +static_assert(comp(height(2 * m) / (3 * m), quantity_kind, one, int>(0))); -static_assert(same(height(2 * m) / (3. * m), +static_assert(comp(height(2 * m) / (3. * m), quantity_kind, one, double>(2 / 3.))); -static_assert(same(height(2. * m) / (3 * m), +static_assert(comp(height(2. * m) / (3 * m), quantity_kind, one, double>(2. / 3))); -static_assert(same((2 * m) / height(3 * m), +static_assert(comp((2 * m) / height(3 * m), quantity_kind, one, int>(0))); -static_assert(same((2 * m) / height(3. * m), +static_assert(comp((2 * m) / height(3. * m), quantity_kind, one, double>(2 / 3.))); -static_assert(same((2. * m) / height(3 * m), +static_assert(comp((2. * m) / height(3 * m), quantity_kind, one, double>(2. / 3))); -static_assert(same(width(8 * m) / width(2 * m), +static_assert(comp(width(8 * m) / width(2 * m), quantity_kind, one, int>(4))); -static_assert(same(width(8 * m) / width(2 * m), +static_assert(comp(width(8 * m) / width(2 * m), quantity_kind, one, double>(4.0))); -static_assert(same(width(8 * m) / width(2 * m), +static_assert(comp(width(8 * m) / width(2 * m), quantity_kind, one, double>(4.0))); -static_assert(same(apples(8) / apples(2), apples(4))); -static_assert(same(apples(8) / (2 / apples(1)), apples(4))); +static_assert(comp(apples(8) / apples(2), apples(4))); +static_assert(comp(apples(8) / (2 / apples(1)), apples(4))); -static_assert(same(horizontal_area(8 * (m * m)) / width(2 * m), width(4 * m))); -static_assert(same(horizontal_area(4 * (m * m)) / (1 * m), width(4 * m))); +static_assert(comp(horizontal_area(8 * (m * m)) / width(2 * m), width(4 * m))); +static_assert(comp(horizontal_area(4 * (m * m)) / (1 * m), width(4 * m))); static_assert(same(width(2 * m) % 3, width(2 * m))); static_assert(same(width(3 * m) % width(2 * m), width(1 * m))); @@ -800,7 +800,7 @@ static_assert(same(quantity_kind_cast(width(1 * static_assert(same(quantity_kind_cast(width(1 * cm)), cgs_width(1 * cgs_cm))); static_assert(same(quantity_kind_cast(width(1 * m)), cgs_width(1 * m))); static_assert(same(quantity_kind_cast(width(1 * m)), cgs_width(1 * m))); -static_assert(same(quantity_kind_cast(width(1 * cm)), width(1 * cgs_cm))); +static_assert(comp(quantity_kind_cast(width(1 * cm)), width(1 * cgs_cm))); static_assert(same(quantity_kind_cast>(width(1 * m)), width(0 * km))); static_assert(same(quantity_kind_cast>(width(1 * m)), width(100 * cm))); static_assert(same(quantity_kind_cast>(width(0.01 * m)), width(1 * cm))); diff --git a/test/unit_test/static/quantity_point_kind_test.cpp b/test/unit_test/static/quantity_point_kind_test.cpp index ab6e3cb6..f8febd8e 100644 --- a/test/unit_test/static/quantity_point_kind_test.cpp +++ b/test/unit_test/static/quantity_point_kind_test.cpp @@ -250,7 +250,7 @@ static_assert(abscissa{}.relative().common() == 0 * m); // CTAD ///////// -static_assert(same(quantity_point_kind(width(0 * m)), abscissa{})); +static_assert(comp(quantity_point_kind(width(0 * m)), abscissa{})); static_assert(same(quantity_point_kind(abscissa(0 * m)), abscissa{})); @@ -500,16 +500,16 @@ static_assert(invalid_compound_assignments_(2 * m) + width(3 * m), abscissa(5 * m))); -static_assert(same(abscissa(2 * m) + width(3. * m), abscissa(5. * m))); -static_assert(same(abscissa(2. * m) + width(3 * m), abscissa(5. * m))); -static_assert(same(abscissa(2 * km) + width(3e3 * m), abscissa(5e3 * m))); -static_assert(same(abscissa(2e3 * m) + width(3 * km), abscissa(5e3 * m))); -static_assert(same(width(2 * m) + abscissa(3 * m), abscissa(5 * m))); -static_assert(same(width(2 * m) + abscissa(3. * m), abscissa(5. * m))); -static_assert(same(width(2. * m) + abscissa(3 * m), abscissa(5. * m))); -static_assert(same(width(2 * km) + abscissa(3e3 * m), abscissa(5e3 * m))); -static_assert(same(width(2e3 * m) + abscissa(3 * km), abscissa(5e3 * m))); +static_assert(comp(abscissa(2 * m) + width(3 * m), abscissa(5 * m))); +static_assert(comp(abscissa(2 * m) + width(3. * m), abscissa(5. * m))); +static_assert(comp(abscissa(2. * m) + width(3 * m), abscissa(5. * m))); +static_assert(comp(abscissa(2 * km) + width(3e3 * m), abscissa(5e3 * m))); +static_assert(comp(abscissa(2e3 * m) + width(3 * km), abscissa(5e3 * m))); +static_assert(comp(width(2 * m) + abscissa(3 * m), abscissa(5 * m))); +static_assert(comp(width(2 * m) + abscissa(3. * m), abscissa(5. * m))); +static_assert(comp(width(2. * m) + abscissa(3 * m), abscissa(5. * m))); +static_assert(comp(width(2 * km) + abscissa(3e3 * m), abscissa(5e3 * m))); +static_assert(comp(width(2e3 * m) + abscissa(3 * km), abscissa(5e3 * m))); static_assert(!std::is_invocable_v, abscissa, double>); static_assert(!std::is_invocable_v, abscissa, length>); static_assert(!std::is_invocable_v, abscissa, quantity_point, metre>>); @@ -522,16 +522,16 @@ static_assert(!std::is_invocable_v, quantity_point, length, abscissa>); static_assert(!std::is_invocable_v, double, abscissa>); -static_assert(same(abscissa(2 * m) - width(3 * m), abscissa(-1 * m))); -static_assert(same(abscissa(2 * m) - width(3. * m), abscissa(-1. * m))); -static_assert(same(abscissa(2. * m) - width(3 * m), abscissa(-1. * m))); -static_assert(same(abscissa(2 * km) - width(3e3 * m), abscissa(-1e3 * m))); -static_assert(same(abscissa(2e3 * m) - width(3 * km), abscissa(-1e3 * m))); +static_assert(comp(abscissa(2 * m) - width(3 * m), abscissa(-1 * m))); +static_assert(comp(abscissa(2 * m) - width(3. * m), abscissa(-1. * m))); +static_assert(comp(abscissa(2. * m) - width(3 * m), abscissa(-1. * m))); +static_assert(comp(abscissa(2 * km) - width(3e3 * m), abscissa(-1e3 * m))); +static_assert(comp(abscissa(2e3 * m) - width(3 * km), abscissa(-1e3 * m))); static_assert(same(abscissa(2 * m) - abscissa(3 * m), width(-1 * m))); static_assert(same(abscissa(2 * m) - abscissa(3. * m), width(-1. * m))); static_assert(same(abscissa(2. * m) - abscissa(3 * m), width(-1. * m))); -static_assert(same(abscissa(2 * km) - abscissa(3e3 * m), width(-1e3 * m))); -static_assert(same(abscissa(2e3 * m) - abscissa(3 * km), width(-1e3 * m))); +static_assert(comp(abscissa(2 * km) - abscissa(3e3 * m), width(-1e3 * m))); +static_assert(comp(abscissa(2e3 * m) - abscissa(3 * km), width(-1e3 * m))); static_assert(!std::is_invocable_v, abscissa, double>); static_assert(!std::is_invocable_v, abscissa, length>); static_assert(!std::is_invocable_v, abscissa, quantity_point, metre>>); @@ -634,41 +634,41 @@ static_assert(same(quantity_point_kind_cast>(abscissa>(abscissa(999 * m)), abscissa(0 * km))); static_assert(same(quantity_point_kind_cast>(abscissa(1000 * m)), abscissa(1 * km))); static_assert(same(quantity_point_kind_cast>(abscissa(999 * m)), abscissa(0.999 * km))); -static_assert(same(quantity_point_kind_cast>(abscissa(1 * m)), abscissa(1 * m))); -static_assert(same(quantity_point_kind_cast>(abscissa(1 * m)), abscissa(1.0 * m))); -static_assert(same(quantity_point_kind_cast>(abscissa(999 * m)), abscissa(0 * km))); -static_assert(same(quantity_point_kind_cast>(abscissa(1000 * m)), abscissa(1 * km))); -static_assert(same(quantity_point_kind_cast>(abscissa(999 * m)), abscissa(0.999 * km))); -static_assert(same(quantity_point_kind_cast(abscissa(1 * m)), abscissa(1.0 * m))); -static_assert(same(quantity_point_kind_cast(abscissa(1 * m)), abscissa(1 * m))); -static_assert(same(quantity_point_kind_cast(abscissa(999 * m)), abscissa(0 * km))); -static_assert(same(quantity_point_kind_cast(abscissa(1000 * m)), abscissa(1 * km))); +static_assert(comp(quantity_point_kind_cast>(abscissa(1 * m)), abscissa(1 * m))); +static_assert(comp(quantity_point_kind_cast>(abscissa(1 * m)), abscissa(1.0 * m))); +static_assert(comp(quantity_point_kind_cast>(abscissa(999 * m)), abscissa(0 * km))); +static_assert(comp(quantity_point_kind_cast>(abscissa(1000 * m)), abscissa(1 * km))); +static_assert(comp(quantity_point_kind_cast>(abscissa(999 * m)), abscissa(0.999 * km))); +static_assert(comp(quantity_point_kind_cast(abscissa(1 * m)), abscissa(1.0 * m))); +static_assert(comp(quantity_point_kind_cast(abscissa(1 * m)), abscissa(1 * m))); +static_assert(comp(quantity_point_kind_cast(abscissa(999 * m)), abscissa(0 * km))); +static_assert(comp(quantity_point_kind_cast(abscissa(1000 * m)), abscissa(1 * km))); static_assert(same(quantity_point_kind_cast>(abscissa(1 * m)), ordinate(1 * m))); static_assert(same(quantity_point_kind_cast>(abscissa(1 * m)), ordinate(1.0 * m))); static_assert(same(quantity_point_kind_cast>(abscissa(999 * m)), ordinate(0 * km))); static_assert(same(quantity_point_kind_cast>(abscissa(1000 * m)), ordinate(1 * km))); static_assert(same(quantity_point_kind_cast>(abscissa(999 * m)), ordinate(0.999 * km))); -static_assert(same(quantity_point_kind_cast>(abscissa(1 * m)), ordinate(1 * m))); -static_assert(same(quantity_point_kind_cast>(abscissa(1 * m)), ordinate(1.0 * m))); -static_assert(same(quantity_point_kind_cast>(abscissa(999 * m)), ordinate(0 * km))); -static_assert(same(quantity_point_kind_cast>(abscissa(1000 * m)), ordinate(1 * km))); -static_assert(same(quantity_point_kind_cast>(abscissa(999 * m)), ordinate(0.999 * km))); -static_assert(same(quantity_point_kind_cast(abscissa(1 * m)), ordinate(1 * m))); +static_assert(comp(quantity_point_kind_cast>(abscissa(1 * m)), ordinate(1 * m))); +static_assert(comp(quantity_point_kind_cast>(abscissa(1 * m)), ordinate(1.0 * m))); +static_assert(comp(quantity_point_kind_cast>(abscissa(999 * m)), ordinate(0 * km))); +static_assert(comp(quantity_point_kind_cast>(abscissa(1000 * m)), ordinate(1 * km))); +static_assert(comp(quantity_point_kind_cast>(abscissa(999 * m)), ordinate(0.999 * km))); +static_assert(comp(quantity_point_kind_cast(abscissa(1 * m)), ordinate(1 * m))); static_assert(same(quantity_point_kind_cast(abscissa(1 * m)), ordinate(1 * m))); static_assert(same(quantity_point_kind_cast(abscissa(999 * m)), ordinate(0 * km))); static_assert(same(quantity_point_kind_cast(abscissa(1000 * m)), ordinate(1 * km))); static_assert(same(quantity_point_kind_cast>(abscissa(1 * cm)), quantity_point_kind(cgs_width(1 * cgs_cm)))); static_assert(same(quantity_point_kind_cast(abscissa(1 * cm)), quantity_point_kind(cgs_width(1 * cgs_cm)))); -static_assert(same(quantity_point_kind_cast(abscissa(1 * cm)), altitude(1 * cgs_cm))); +static_assert(comp(quantity_point_kind_cast(abscissa(1 * cm)), altitude(1 * cgs_cm))); static_assert(same(quantity_point_kind_cast(abscissa(1 * cm)), altitude(1 * cgs_cm))); static_assert(same(quantity_point_kind_cast(abscissa(1 * m)), quantity_point_kind(cgs_width(1 * m)))); -static_assert(same(quantity_point_kind_cast(abscissa(1 * m)), altitude(1 * m))); +static_assert(comp(quantity_point_kind_cast(abscissa(1 * m)), altitude(1 * m))); static_assert(same(quantity_point_kind_cast(abscissa(1 * m)), altitude(1 * m))); -static_assert(same(quantity_point_kind_cast(abscissa(1 * cm)), abscissa(1 * cgs_cm))); -static_assert(same(quantity_point_kind_cast>(abscissa(1 * m)), abscissa(0 * km))); -static_assert(same(quantity_point_kind_cast>(abscissa(1 * m)), abscissa(100 * cm))); -static_assert(same(quantity_point_kind_cast>(abscissa(0.01 * m)), abscissa(1 * cm))); -static_assert(same(quantity_point_kind_cast>(abscissa(1 * cgs_cm)), abscissa(1 * cgs_cm))); +static_assert(comp(quantity_point_kind_cast(abscissa(1 * cm)), abscissa(1 * cgs_cm))); +static_assert(comp(quantity_point_kind_cast>(abscissa(1 * m)), abscissa(0 * km))); +static_assert(comp(quantity_point_kind_cast>(abscissa(1 * m)), abscissa(100 * cm))); +static_assert(comp(quantity_point_kind_cast>(abscissa(0.01 * m)), abscissa(1 * cm))); +static_assert(comp(quantity_point_kind_cast>(abscissa(1 * cgs_cm)), abscissa(1 * cgs_cm))); static_assert(same(quantity_point_kind_cast>(screen_si_width(1 * m)), screen_si_cgs_width(1 * m))); // clang-format on template diff --git a/test/unit_test/static/quantity_test.cpp b/test/unit_test/static/quantity_test.cpp index 73985198..1c0ad9d2 100644 --- a/test/unit_test/static/quantity_test.cpp +++ b/test/unit_test/static/quantity_test.cpp @@ -275,11 +275,11 @@ struct derived_quantity : quantity static_assert(detail::is_quantity, "NTTP type description">>); constexpr isq::Length auto get_length_derived_quantity() noexcept { - derived_quantity, "NTTP type description"> a{}; - a += 1_q_m; - a = a + 1_q_m; - a *= 0.5; - return a; + derived_quantity, "NTTP type description"> dist{}; + dist += 1_q_m; + dist = dist + 1_q_m; + dist *= 0.5; + return dist; } static_assert(get_length_derived_quantity() == 1_q_m); @@ -479,11 +479,11 @@ static_assert(invalid_binary_operations); static_assert(is_same_v>); static_assert(is_same_v>); static_assert(is_same_v>); -static_assert(is_same_v>); +static_assert(compare>); static_assert(is_same_v>); -static_assert(is_same_v>); +static_assert(compare>); static_assert(is_same_v>); -static_assert(is_same_v>); +static_assert(compare>); static_assert(is_same_v>); static_assert(is_same_v>); static_assert(is_same_v>); @@ -513,12 +513,12 @@ static_assert( is_same_v>); // TODO should we address fundamental types implicit // truncating conversions with concepts? static_assert(is_same_v>); -static_assert(is_same_v>); // TODO should we address fundamental types implicit truncating - // conversions with concepts? -static_assert(is_same_v>); +static_assert(compare>); // TODO should we address fundamental types implicit truncating + // conversions with concepts? +static_assert(compare>); static_assert(is_same_v>); -static_assert(is_same_v>); +static_assert(compare>); static_assert(compare(1)), length>); static_assert(compare(1) * 1._q_m), length>); static_assert(compare>); @@ -537,10 +537,10 @@ static_assert(is_same_v>); static_assert(is_same_v>); static_assert(is_same_v>); static_assert(is_same_v>); -static_assert(is_same_v>); -static_assert(is_same_v>); +static_assert(compare>); +static_assert(compare>); static_assert(is_same_v>); -static_assert(is_same_v>); +static_assert(compare>); static_assert(compare(1)), length>); static_assert(compare(1) * 1_q_m), length>); static_assert(compare(1)), length>); @@ -552,25 +552,25 @@ static_assert(compare(1) / 1_q_s), frequency(), hertz>, long double>>); // different units -static_assert(is_same_v>); -static_assert(is_same_v>); -static_assert(is_same_v>); -static_assert(is_same_v>); +static_assert(compare>); +static_assert(compare>); +static_assert(compare>); +static_assert(compare>); -static_assert(is_same_v>); -static_assert(is_same_v>); -static_assert(is_same_v>); -static_assert(is_same_v>); +static_assert(compare>); +static_assert(compare>); +static_assert(compare>); +static_assert(compare>); -static_assert(is_same_v>); -static_assert(is_same_v>); -static_assert(is_same_v>); -static_assert(is_same_v>); +static_assert(compare>); +static_assert(compare>); +static_assert(compare>); +static_assert(compare>); -static_assert(is_same_v>); -static_assert(is_same_v>); -static_assert(is_same_v>); -static_assert(is_same_v>); +static_assert(compare>); +static_assert(compare>); +static_assert(compare>); +static_assert(compare>); static_assert(is_same_v>); static_assert(is_same_v>); @@ -891,8 +891,8 @@ static_assert( #else -static_assert(is_same_v>); -static_assert(is_same_v>); +static_assert(compare>); +static_assert(compare>); #endif @@ -906,19 +906,19 @@ constexpr auto quotient_remainder_theorem(auto q1, auto q2) return q; } -static_assert(same(quotient_remainder_theorem(3'000 * m, 400 * m), 3'000 * m)); -static_assert(same(quotient_remainder_theorem(3 * km, 400 * m), 3 * km)); -static_assert(same(quotient_remainder_theorem(3 * km, 2 * m), 3 * km)); -static_assert(same(quotient_remainder_theorem(3 * km, 400'000 * mm), 3 * km)); -static_assert(same(quotient_remainder_theorem(3 * km, 2'000 * mm), 3 * km)); -static_assert(same(quotient_remainder_theorem(3 * km, 400 * mm), 3 * km)); -static_assert(same(quotient_remainder_theorem(3 * km, 2 * mm), 3 * km)); +static_assert(comp(quotient_remainder_theorem(3'000 * m, 400 * m), 3'000 * m)); +static_assert(comp(quotient_remainder_theorem(3 * km, 400 * m), 3 * km)); +static_assert(comp(quotient_remainder_theorem(3 * km, 2 * m), 3 * km)); +static_assert(comp(quotient_remainder_theorem(3 * km, 400'000 * mm), 3 * km)); +static_assert(comp(quotient_remainder_theorem(3 * km, 2'000 * mm), 3 * km)); +static_assert(comp(quotient_remainder_theorem(3 * km, 400 * mm), 3 * km)); +static_assert(comp(quotient_remainder_theorem(3 * km, 2 * mm), 3 * km)); static_assert(same(quotient_remainder_theorem(3'000 * m, 400), 3'000 * m)); -static_assert(same(quotient_remainder_theorem(3'000 * m, quantity(400)), 3'000 * m)); -static_assert(same(quotient_remainder_theorem(3 * km, quantity(400)), 3 * km)); -static_assert(same(quotient_remainder_theorem(3 * km, quantity(2)), 3 * km)); +static_assert(comp(quotient_remainder_theorem(3'000 * m, quantity(400)), 3'000 * m)); +static_assert(comp(quotient_remainder_theorem(3 * km, quantity(400)), 3 * km)); +static_assert(comp(quotient_remainder_theorem(3 * km, quantity(2)), 3 * km)); static_assert( - same(quotient_remainder_theorem(3 * km, dimensionless(), one>, int>(400)), + comp(quotient_remainder_theorem(3 * km, dimensionless(), one>, int>(400)), 3 * km)); } // namespace diff --git a/test/unit_test/static/references_test.cpp b/test/unit_test/static/references_test.cpp index ef128436..56714358 100644 --- a/test/unit_test/static/references_test.cpp +++ b/test/unit_test/static/references_test.cpp @@ -20,6 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +#include "test_tools.h" #include #include #include @@ -70,8 +71,8 @@ static_assert([] { const auto duration{2}; return length * km / (duration * h); }() == 60_q_km_per_h); -static_assert(is_same_v); -static_assert(is_same_v); +static_assert(compare); +static_assert(compare); static_assert(1. / 4 * m2 == 1._q_m2 / 4); diff --git a/test/unit_test/static/si_hep_test.cpp b/test/unit_test/static/si_hep_test.cpp index 914ceddd..87045e63 100644 --- a/test/unit_test/static/si_hep_test.cpp +++ b/test/unit_test/static/si_hep_test.cpp @@ -40,8 +40,6 @@ static_assert(si::mass(1'000) == si::hep::mass(1'000'000) == si::hep::momentum(1)); -static_assert(si::hep::momentum(1'000'000) == si::momentum(1)); -static_assert(si::momentum(1'000'000) == si::hep::momentum(1)); // area static_assert(si::area(1e28) == si::area(1)); diff --git a/test/unit_test/static/si_test.cpp b/test/unit_test/static/si_test.cpp index 9070110d..bbd81a8e 100644 --- a/test/unit_test/static/si_test.cpp +++ b/test/unit_test/static/si_test.cpp @@ -276,8 +276,17 @@ static_assert(10_q_m * 10_q_m == 100_q_m2); static_assert(100_q_m2 / 10_q_m == 10_q_m); static_assert(10_q_km * 10_q_km == 100_q_km2); static_assert(1_q_m2 == 10'000_q_cm2); + +static_assert(1_q_ca == 1_q_m2); +static_assert(1_q_da == 10_q_m2); +static_assert(1_q_a == 100_q_m2); +static_assert(1_q_daa == 1'000_q_m2); static_assert(1_q_ha == 10'000_q_m2); +static_assert(centiare::symbol == "ca"); +static_assert(deciare::symbol == "da"); +static_assert(are::symbol == "a"); +static_assert(decare::symbol == "daa"); static_assert(hectare::symbol == "ha"); static_assert(detail::unit_text() == basic_symbol_text("m²", "m^2")); diff --git a/test/unit_test/static/test_tools.h b/test/unit_test/static/test_tools.h index 70ef41a1..4116ed7c 100644 --- a/test/unit_test/static/test_tools.h +++ b/test/unit_test/static/test_tools.h @@ -123,16 +123,9 @@ constexpr bool ctad_constructible_from(Vs...) return ctad_constructible_from_; } -#if UNITS_DOWNCAST_MODE constexpr auto same = [](T l, T r) { return l == r; }; -#else -constexpr auto same = [](T l, U r) - requires requires { l == r; } -// requires std::equality_comparable_with // TODO: Fix #205 -{ - return l == r; -}; -#endif +constexpr auto comp = // TODO: Fix #205 to use `std::equality_comparable_with U`. + [](T l, U r) requires compare { return l == r; }; template requires requires { F(); } diff --git a/test/unit_test/static/type_list_test.cpp b/test/unit_test/static/type_list_test.cpp index 186e0ba0..81f39586 100644 --- a/test/unit_test/static/type_list_test.cpp +++ b/test/unit_test/static/type_list_test.cpp @@ -94,9 +94,9 @@ static_assert( is_same_v>::second_list, type_list>); // type_list_merge_sorted -struct u0 : named_unit {}; +struct u0 : named_unit {}; struct d0 : base_dimension<"d0", u0> {}; -struct u1 : named_unit {}; +struct u1 : named_unit {}; struct d1 : base_dimension<"d1", u1> {}; static_assert( diff --git a/test/unit_test/static/unit_test.cpp b/test/unit_test/static/unit_test.cpp index cac1c622..128fac3d 100644 --- a/test/unit_test/static/unit_test.cpp +++ b/test/unit_test/static/unit_test.cpp @@ -33,29 +33,29 @@ namespace { using namespace units; using namespace units::isq; -struct metre : named_unit {}; +struct metre : named_unit {}; struct centimetre : prefixed_unit {}; struct kilometre : prefixed_unit {}; -struct yard : named_scaled_unit(), metre> {}; -struct foot : named_scaled_unit(), yard> {}; +struct yard : named_scaled_unit(), metre> {}; +struct foot : named_scaled_unit(), yard> {}; struct dim_length : base_dimension<"length", metre> {}; -struct second : named_unit {}; -struct hour : named_scaled_unit(), second> {}; +struct second : named_unit {}; +struct hour : named_scaled_unit(), second> {}; struct dim_time : base_dimension<"time", second> {}; -struct kelvin : named_unit {}; +struct kelvin : named_unit {}; #if !UNITS_COMP_MSVC static_assert([](P) { - return !requires { typename prefixed_unit; }; + return !requires { typename prefixed_unit; }; }(si::kilo{})); // no prefix allowed #endif -struct metre_per_second : unit {}; +struct metre_per_second : derived_unit {}; struct dim_speed : derived_dimension, units::exponent> {}; -struct kilometre_per_hour : derived_unit {}; +struct kilometre_per_hour : derived_scaled_unit {}; static_assert(equivalent); static_assert(equivalent); diff --git a/test_package/conanfile.py b/test_package/conanfile.py index babc60b1..1afb178a 100644 --- a/test_package/conanfile.py +++ b/test_package/conanfile.py @@ -20,12 +20,18 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from conans import ConanFile, tools +from conan import ConanFile from conan.tools.cmake import CMake +from conan.tools.build import cross_building + class TestPackageConan(ConanFile): settings = "os", "compiler", "build_type", "arch" generators = "CMakeToolchain", "CMakeDeps" + test_type = "explicit" # TODO Remove for Conan 2.0 + + def requirements(self): + self.requires(self.tested_reference_str) def build(self): cmake = CMake(self) @@ -33,5 +39,5 @@ class TestPackageConan(ConanFile): cmake.build() def test(self): - if not tools.cross_building(self.settings): + if not cross_building(self): self.run("test_package", run_environment=True)