Merge branch 'mpusz:master' into master

This commit is contained in:
Ralph J. Steinhagen
2021-07-19 09:45:13 +02:00
committed by GitHub
211 changed files with 2025 additions and 1245 deletions

View File

@@ -63,7 +63,7 @@ CommentPragmas: '^ NOLINT'
# CompactNamespaces: false # CompactNamespaces: false
# ConstructorInitializerAllOnOneLineOrOnePerLine: true # ConstructorInitializerAllOnOneLineOrOnePerLine: true
# ConstructorInitializerIndentWidth: 4 # ConstructorInitializerIndentWidth: 4
# ContinuationIndentWidth: 4 ContinuationIndentWidth: 2
# Cpp11BracedListStyle: true # Cpp11BracedListStyle: true
DeriveLineEnding: false DeriveLineEnding: false
DerivePointerAlignment: false DerivePointerAlignment: false
@@ -109,7 +109,7 @@ IndentRequires: true
# KeepEmptyLinesAtTheStartOfBlocks: false # KeepEmptyLinesAtTheStartOfBlocks: false
# MacroBlockBegin: '' # MacroBlockBegin: ''
# MacroBlockEnd: '' # MacroBlockEnd: ''
# MaxEmptyLinesToKeep: 1 MaxEmptyLinesToKeep: 2
# NamespaceIndentation: None # NamespaceIndentation: None
# ObjCBinPackProtocolList: Never # ObjCBinPackProtocolList: Never
# ObjCBlockIndentWidth: 2 # ObjCBlockIndentWidth: 2

View File

@@ -78,6 +78,11 @@ jobs:
downcast_mode: [ "on", "auto" ] downcast_mode: [ "on", "auto" ]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: hendrikmuhs/ccache-action@v1
if: runner.os == 'Linux'
with:
key: ${{ matrix.config.os }}-${{ matrix.config.compiler.type }}-${{ matrix.config.compiler.version }}-${{ matrix.config.lib }}-${{ matrix.build_type }}-${{ matrix.downcast_mode }}
max-size: 50M
- name: Install Clang - name: Install Clang
if: matrix.config.compiler.type == 'CLANG' if: matrix.config.compiler.type == 'CLANG'
shell: bash shell: bash
@@ -121,12 +126,6 @@ jobs:
conan profile update settings.compiler.libcxx=${{ matrix.config.lib }} default conan profile update settings.compiler.libcxx=${{ matrix.config.lib }} default
fi fi
conan profile show default conan profile show default
- name: Add support for clang-12 to Conan's settings.yml
# TODO Remove when Conan will support clang-12 (after clang-12 release)
if: matrix.config.compiler.type == 'CLANG'
shell: bash
run: |
sed -i -e 's/"8", "9", "10", "11"]/"8", "9", "10", "11", "12"]/' ~/.conan/settings.yml
- name: Run Conan Package Tools - name: Run Conan Package Tools
shell: bash shell: bash
env: env:

View File

@@ -84,6 +84,7 @@ jobs:
CC: ${{ matrix.config.compiler.cc }} CC: ${{ matrix.config.compiler.cc }}
CXX: ${{ matrix.config.compiler.cxx }} CXX: ${{ matrix.config.compiler.cxx }}
CMAKE_GENERATOR: Ninja CMAKE_GENERATOR: Ninja
CONAN_CMAKE_GENERATOR: Ninja
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@@ -143,18 +144,20 @@ jobs:
conan profile update settings.compiler.libcxx=${{ matrix.config.lib }} default conan profile update settings.compiler.libcxx=${{ matrix.config.lib }} default
fi fi
conan profile show default conan profile show default
- name: Add support for clang-12 to Conan's settings.yml
# TODO Remove when Conan will support clang-12 (after clang-12 release)
if: matrix.config.compiler.type == 'CLANG'
shell: bash
run: |
sed -i -e 's/"8", "9", "10", "11"]/"8", "9", "10", "11", "12"]/' ~/.conan/settings.yml
- name: Install Conan dependencies - name: Install Conan dependencies
shell: bash shell: bash
run: | run: |
mkdir -p build/${{ matrix.build_type }} && cd build/${{ matrix.build_type }} mkdir -p build/${{ matrix.build_type }} && cd build/${{ matrix.build_type }}
conan install ../.. -b outdated -u conan install ../.. -b outdated -u
- name: Configure mp-units CMake - name: Configure mp-units CMake
if: matrix.config.compiler.type == 'VISUAL'
shell: cmd
working-directory: build/${{ matrix.build_type }}
run: |
call conanvcvars.bat
cmake ../../src -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
- name: Configure mp-units CMake
if: matrix.config.compiler.type != 'VISUAL'
shell: bash shell: bash
working-directory: build/${{ matrix.build_type }} working-directory: build/${{ matrix.build_type }}
run: | run: |
@@ -164,16 +167,25 @@ jobs:
working-directory: build/${{ matrix.build_type }} working-directory: build/${{ matrix.build_type }}
run: | run: |
cmake --install . --prefix test_package cmake --install . --prefix test_package
- name: Configure test_package CMake - name: Install dependencies for test_package
shell: bash shell: bash
run: | run: |
mkdir -p test_package/build/${{ matrix.build_type }} && cd test_package/build/${{ matrix.build_type }} mkdir -p test_package/build/${{ matrix.build_type }} && cd test_package/build/${{ matrix.build_type }}
conan install ../../.. conan install ../../..
- name: Build test_package CMake
if: matrix.config.compiler.type == 'VISUAL'
shell: cmd
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_INSTALL_PREFIX=../../../build/${{ matrix.build_type }}/test_package
- name: Build test_package cmake --build .
- name: Build test_package CMake
if: matrix.config.compiler.type != 'VISUAL'
shell: bash shell: bash
working-directory: test_package/build/${{ matrix.build_type }} working-directory: test_package/build/${{ matrix.build_type }}
run: | run: |
cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_INSTALL_PREFIX=../../../build/${{ matrix.build_type }}/test_package
cmake --build . cmake --build .
- name: Run test_package - name: Run test_package
shell: bash shell: bash

View File

@@ -84,7 +84,7 @@ jobs:
pip install -U conan pip install -U conan
conan config init conan config init
conan remote add upload https://mpusz.jfrog.io/artifactory/api/conan/conan-oss conan remote add upload https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
conan remote add linear-algebra https://api.bintray.com/conan/twonington/public-conan conan remote add linear-algebra https://twonington.jfrog.io/artifactory/api/conan/conan-oss
mkdir _lgtm_build_dir && cd _lgtm_build_dir mkdir _lgtm_build_dir && cd _lgtm_build_dir
conan install .. -s compiler.cppstd=20 -s compiler.libcxx=libstdc++11 -o mp-units:build_docs=False -e mp-units:CONAN_RUN_TESTS=True -b outdated -u conan install .. -s compiler.cppstd=20 -s compiler.libcxx=libstdc++11 -o mp-units:build_docs=False -e mp-units:CONAN_RUN_TESTS=True -b outdated -u
conan build .. conan build ..

View File

@@ -40,6 +40,7 @@ env:
CC: gcc-10 CC: gcc-10
CXX: g++-10 CXX: g++-10
CMAKE_GENERATOR: Ninja CMAKE_GENERATOR: Ninja
CONAN_CMAKE_GENERATOR: Ninja
jobs: jobs:
docs: docs:
@@ -75,7 +76,7 @@ jobs:
run: | run: |
conan config init conan config init
conan remote add -i 0 upload https://mpusz.jfrog.io/artifactory/api/conan/conan-oss conan remote add -i 0 upload https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
conan remote add linear-algebra https://api.bintray.com/conan/twonington/public-conan conan remote add linear-algebra https://twonington.jfrog.io/artifactory/api/conan/conan-oss
- name: Install Conan dependencies - name: Install Conan dependencies
run: | run: |
mkdir build && cd build mkdir build && cd build

1
.gitignore vendored
View File

@@ -38,6 +38,7 @@
/cmake-build-*/ /cmake-build-*/
/build/ /build/
/out/ /out/
_build/
# Conan # Conan
*.pyc *.pyc

View File

@@ -27,6 +27,14 @@ project(mp-units-dev
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
# make sure that the file is being used as an entry point
include(modern_project_structure)
ensure_entry_point()
# use ccache if available
include(ccache)
enable_ccache(BASE_DIR ${PROJECT_SOURCE_DIR})
# set restrictive compilation warnings # set restrictive compilation warnings
include(warnings) include(warnings)
set_warnings() set_warnings()
@@ -38,7 +46,7 @@ add_compile_definitions($<$<CONFIG:Debug>:gsl_CONFIG_CONTRACT_CHECKING_AUDIT>)
option(UNITS_IWYU "Enables include-what-you-use" OFF) option(UNITS_IWYU "Enables include-what-you-use" OFF)
if(UNITS_IWYU) if(UNITS_IWYU)
include(include-what-you-use) include(include-what-you-use)
set_iwyu( enable_iwyu(
MAPPING_FILE "${PROJECT_SOURCE_DIR}/.mp-units.imp" MAPPING_FILE "${PROJECT_SOURCE_DIR}/.mp-units.imp"
NO_FORWARD_DECLARATIONS NO_FORWARD_DECLARATIONS
QUOTED_INCLUDES_FIRST QUOTED_INCLUDES_FIRST

View File

@@ -2,8 +2,8 @@
[![Conan CI](https://img.shields.io/github/workflow/status/mpusz/units/Conan%20CI/master?label=Conan%20CI)](https://github.com/mpusz/units/actions?query=workflow%3A%22Conan%20CI%22+branch%3Amaster) [![Conan CI](https://img.shields.io/github/workflow/status/mpusz/units/Conan%20CI/master?label=Conan%20CI)](https://github.com/mpusz/units/actions?query=workflow%3A%22Conan%20CI%22+branch%3Amaster)
[![CMake CI](https://img.shields.io/github/workflow/status/mpusz/units/CMake%20Test%20Package%20CI/master?label=CMake%20CI)](https://github.com/mpusz/units/actions?query=workflow%3A%22CMake+Test+Package+CI%22+branch%3Amaster) [![CMake CI](https://img.shields.io/github/workflow/status/mpusz/units/CMake%20Test%20Package%20CI/master?label=CMake%20CI)](https://github.com/mpusz/units/actions?query=workflow%3A%22CMake+Test+Package+CI%22+branch%3Amaster)
[![GitHub Workflow Documentation](https://img.shields.io/github/workflow/status/mpusz/units/Documentation/master?label=Documentation%20CI)](https://github.com/mpusz/units/actions?query=workflow%3ADocumentation+branch%3Amaster) [![GitHub Workflow Documentation](https://img.shields.io/github/workflow/status/mpusz/units/Documentation/master?label=Documentation%20CI)](https://github.com/mpusz/units/actions?query=workflow%3ADocumentation+branch%3Amaster)
[![Conan stable](https://img.shields.io/badge/ConanCenter-0.6.0%3Astable-blue)](https://conan.io/center/mp-units) [![Conan stable](https://img.shields.io/badge/ConanCenter-0.7.0%3Astable-blue)](https://conan.io/center/mp-units)
[![Conan testing](https://img.shields.io/badge/mpusz.jfrog.io-0.7.0%3Atesting-blue)](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units/0.7.0) [![Conan testing](https://img.shields.io/badge/mpusz.jfrog.io-0.8.0%3Atesting-blue)](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units/0.8.0)
# `mp-units` - A Units Library for C++ # `mp-units` - A Units Library for C++
@@ -28,8 +28,6 @@ analysis and unit/quantity manipulation. The basic idea and design heavily bases
Here is a small example of possible operations: Here is a small example of possible operations:
```cpp ```cpp
#define UNITS_REFERENCES
#include <units/isq/si/area.h> #include <units/isq/si/area.h>
#include <units/isq/si/frequency.h> #include <units/isq/si/frequency.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
@@ -58,7 +56,7 @@ static_assert(10 * km / (5 * km) == 2);
static_assert(1000 / (1 * s) == 1 * kHz); static_assert(1000 / (1 * s) == 1 * kHz);
``` ```
_Try it on the [Compiler Explorer](https://godbolt.org/z/53bTahKd8)._ _Try it on the [Compiler Explorer](https://godbolt.org/z/5dvY8Woh1)._
This library requires some C++20 features (concepts, classes as NTTPs, ...). Thanks to This library requires some C++20 features (concepts, classes as NTTPs, ...). Thanks to
them the user gets a powerful but still easy to use interface and all unit conversions them the user gets a powerful but still easy to use interface and all unit conversions
@@ -66,10 +64,6 @@ and dimensional analysis can be performed without sacrificing on accuracy. Pleas
the below example for a quick preview of basic library features: the below example for a quick preview of basic library features:
```cpp ```cpp
#define UNITS_ALIASES
#define UNITS_LITERALS
#define UNITS_REFERENCES
#include <units/format.h> #include <units/format.h>
#include <units/isq/si/international/length.h> #include <units/isq/si/international/length.h>
#include <units/isq/si/international/speed.h> #include <units/isq/si/international/speed.h>
@@ -115,4 +109,4 @@ int main()
} }
``` ```
_Try it on the [Compiler Explorer](https://godbolt.org/z/jKnPPPEx6)._ _Try it on the [Compiler Explorer](https://godbolt.org/z/9fnzfbhb6)._

View File

@@ -36,7 +36,7 @@ if __name__ == "__main__":
# dependencies # dependencies
remotes = [ remotes = [
("https://api.bintray.com/conan/twonington/public-conan", True, "linear-algebra") ("https://twonington.jfrog.io/artifactory/api/conan/conan-oss", True, "linear-algebra")
], ],
build_policy = ["mp-units", "outdated"], build_policy = ["mp-units", "outdated"],
upload_dependencies = "all", upload_dependencies = "all",

221
cmake/ccache.cmake Normal file
View File

@@ -0,0 +1,221 @@
# The MIT License (MIT)
#
# Copyright (c) 2017 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.4)
macro(_enable_ccache_failed)
if(NOT _enable_ccache_QUIET)
message(STATUS "Enabling ccache - failed")
endif()
return()
endmacro()
#
# enable_ccache([PROGRAM] # ccache by default
# [QUIET] [REQUIRED]
# [MODE DIRECT_PREPROCESSOR|DIRECT_DEPEND|PREPROCESSOR|DEPEND] # DIRECT_PREPROCESSOR by default
# [BASE_DIR dir]
# [ACCOUNT_FOR_COMPILE_TIME_HEADER_CHANGES]
# [ACCOUNT_FOR_PCH]
# [ACCOUNT_FOR_MODULES]
# [PREFIXES prefixes...]
# )
#
# BASE_DIR
# Set this option to ${CMAKE_BINARY_DIR} if you use FetchContent a lot for many projects with the same build options.
# Otherwise, if most of the sources come from the project itself then the default ${CMAKE_SOURCE_DIR} may be
# a better choice.
#
# ACCOUNT_FOR_COMPILE_TIME_HEADER_CHANGES
# Use it if some header files are being generated by the compilation process.
#
# ACCOUNT_FOR_PCH
# Use it if precompiled headers are enabled in your project. Automatically includes uses
# ACCOUNT_FOR_COMPILE_TIME_HEADER_CHANGES as well.
# See here for details: https://ccache.dev/manual/4.2.1.html#_precompiled_headers
#
# ACCOUNT_FOR_MODULES
# Use it for projects with C++20 modules. Requires DIRECT_DEPEND mode.
#
# PREFIXES
# A list of other tools that should be used together with ccache as a compiler launcher
# (i.e. distcc, icecc, sccache-dist, ...).
#
function(enable_ccache)
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
message(FATAL_ERROR "'enable_ccache' function should be called from the top-level CMakeLists.txt file!")
# otherwise, it will not work for XCode
endif()
set(_options QUIET REQUIRED ACCOUNT_FOR_COMPILE_TIME_HEADER_CHANGES ACCOUNT_FOR_PCH ACCOUNT_FOR_MODULES)
set(_one_value_args PROGRAM MODE BASE_DIR)
set(_multi_value_args PREFIXES)
cmake_parse_arguments(PARSE_ARGV 0 _enable_ccache "${_options}" "${_one_value_args}" "${_multi_value_args}")
# validate and process arguments
if(_enable_ccache_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Invalid arguments '${_enable_ccache_UNPARSED_ARGUMENTS}'")
endif()
if(_enable_ccache_KEYWORDS_MISSING_VALUES)
message(FATAL_ERROR "No value provided for '${_enable_ccache_KEYWORDS_MISSING_VALUES}'")
endif()
if(_enable_ccache_MODE)
set(_valid_mode_values DIRECT_PREPROCESSOR DIRECT_DEPEND PREPROCESSOR DEPEND)
if(NOT _enable_ccache_MODE IN_LIST _valid_mode_values)
message(FATAL_ERROR "'MODE' should be one of ${_valid_mode_values}")
endif()
endif()
if(NOT _enable_ccache_QUIET)
message(STATUS "Enabling ccache")
endif()
if(${_enable_ccache_REQUIRED})
set(_error_log_level FATAL_ERROR)
elseif(NOT _enable_ccache_QUIET)
set(_error_log_level STATUS)
endif()
if(NOT CMAKE_GENERATOR MATCHES "Ninja|Makefiles|Xcode")
if(DEFINED _error_log_level)
message(${_error_log_level} "ccache support not enabled: unsupported generator '${CMAKE_GENERATOR}'")
endif()
_enable_ccache_failed()
endif()
if(NOT DEFINED _enable_ccache_PROGRAM)
set(_enable_ccache_PROGRAM ccache)
endif()
find_program(CCACHE_PATH ${_enable_ccache_PROGRAM})
if(CCACHE_PATH)
if(NOT _enable_ccache_QUIET)
message(STATUS " Executable: ${CCACHE_PATH}")
endif()
# get version number
execute_process(COMMAND "${CCACHE_PATH}" --version OUTPUT_VARIABLE _output)
string(REPLACE "\n" ";" _output "${_output}")
foreach(_line ${_output})
string(REGEX REPLACE "ccache version ([\\.0-9]+)$" "\\1" _ccache_version "${_line}")
if(_ccache_version)
if(NOT _enable_ccache_QUIET)
message(STATUS " Version: ${_ccache_version}")
endif()
break()
endif()
endforeach()
else()
if(DEFINED _error_log_level)
message(${_error_log_level} " '${_enable_ccache_PROGRAM}' executable was not found")
endif()
_enable_ccache_failed()
endif()
if("${_ccache_version}" VERSION_LESS 3.3.0)
list(APPEND _ccacheEnv CCACHE_CPP2=1) # avoids spurious warnings with some compilers for ccache older than 3.3
endif()
if(_enable_ccache_MODE STREQUAL DIRECT_DEPEND)
list(APPEND _ccacheEnv CCACHE_DIRECT=1 CCACHE_DEPEND=1)
elseif(_enable_ccache_MODE STREQUAL PREPROCESSOR)
list(APPEND _ccacheEnv CCACHE_NO_DIRECT=1 CCACHE_NO_DEPEND=1)
elseif(_enable_ccache_MODE STREQUAL DEPEND)
list(APPEND _ccacheEnv CCACHE_NO_DIRECT=1 CCACHE_DEPEND=1)
else()
set(_enable_ccache_MODE DIRECT_PREPROCESSOR)
list(APPEND _ccacheEnv CCACHE_DIRECT=1 CCACHE_NO_DEPEND=1)
endif()
if(_enable_ccache_BASE_DIR)
# CCACHE_ABSSTDERR=1 # reverts absolute paths after applying CCACHE_BASEDIR
if(NOT EXISTS ${_enable_ccache_BASE_DIR})
message(FATAL_ERROR "Base directory '${_enable_ccache_BASE_DIR}' does not exist")
endif()
list(APPEND _ccacheEnv "CCACHE_BASEDIR=${_enable_ccache_BASE_DIR}")
endif()
if(_enable_ccache_PREFIXES)
string(REPLACE ";" " " _prefixes_txt "${_enable_ccache_PREFIXES}")
list(APPEND _ccacheEnv "CCACHE_PREFIX=${_prefixes_txt}")
endif()
if(_enable_ccache_ACCOUNT_FOR_COMPILE_TIME_HEADER_CHANGES)
list(APPEND _sloppiness include_file_mtime include_file_ctime)
endif()
if(_enable_ccache_ACCOUNT_FOR_PCH)
list(APPEND _sloppiness pch_defines time_macros include_file_mtime include_file_ctime)
endif()
if(_enable_ccache_ACCOUNT_FOR_MODULES)
if(NOT _enable_ccache_MODE STREQUAL DIRECT_DEPEND)
message(FATAL_ERROR "DIRECT_DEPEND mode required with ACCOUNT_FOR_MODULES option")
endif()
list(APPEND _sloppiness modules)
endif()
if(_sloppiness)
list(REMOVE_DUPLICATES _sloppiness)
string(REPLACE ";" "," _sloppiness_txt "${_sloppiness}")
list(APPEND _ccacheEnv "CCACHE_SLOPPINESS=${_sloppiness_txt}")
endif()
if(NOT _enable_ccache_QUIET)
message(STATUS " Environment: ${_ccacheEnv}")
endif()
if(CMAKE_GENERATOR MATCHES "Ninja|Makefiles")
foreach(_lang IN ITEMS C CXX OBJC OBJCXX CUDA)
set(CMAKE_${_lang}_COMPILER_LAUNCHER
${CMAKE_COMMAND} -E env
${_ccacheEnv} ${CCACHE_PATH}
PARENT_SCOPE
)
endforeach()
elseif(CMAKE_GENERATOR STREQUAL Xcode)
# Each of the Xcode project variables allow specifying only a single value, but the ccache command line needs to have multiple options.
# A separate launch script needs to be written out and the project variables pointed at them.
foreach(_lang IN ITEMS C CXX)
set(launch${_lang} ${CMAKE_BINARY_DIR}/launch-${_lang})
file(WRITE ${launch${_lang}} "#!/bin/bash\n\n")
foreach(keyVal IN LISTS _ccacheEnv)
file(APPEND ${launch${_lang}} "export ${keyVal}\n")
endforeach()
file(APPEND ${launch${_lang}}
"exec \"${CCACHE_PROGRAM}\" "
"\"${CMAKE_${_lang}_COMPILER}\" \"$@\"\n"
)
execute_process(COMMAND chmod a+rx ${launch${_lang}})
endforeach()
set(CMAKE_XCODE_ATTRIBUTE_CC ${launchC} PARENT_SCOPE)
set(CMAKE_XCODE_ATTRIBUTE_CXX ${launchCXX} PARENT_SCOPE)
set(CMAKE_XCODE_ATTRIBUTE_LD ${launchC} PARENT_SCOPE)
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS ${launchCXX} PARENT_SCOPE)
endif()
if(NOT _enable_ccache_QUIET)
message(STATUS "Enabling ccache - done")
endif()
endfunction()

View File

@@ -49,7 +49,7 @@ function(add_documentation targetName)
if(NOT _args_DOXYFILE_TEMPLATE) if(NOT _args_DOXYFILE_TEMPLATE)
set(_args_DOXYFILE_TEMPLATE Doxyfile.in) set(_args_DOXYFILE_TEMPLATE Doxyfile.in)
endif() endif()
file(REAL_PATH ${_args_DOXYFILE_TEMPLATE} _doxyfileIn) get_filename_component(_doxyfileIn ${_args_DOXYFILE_TEMPLATE} REALPATH)
if(NOT EXISTS ${_doxyfileIn}) if(NOT EXISTS ${_doxyfileIn})
message(FATAL_ERROR "'${_args_DOXYFILE_TEMPLATE}' does not exist") message(FATAL_ERROR "'${_args_DOXYFILE_TEMPLATE}' does not exist")
endif() endif()

View File

@@ -30,53 +30,82 @@ endif()
set(IWYU_VERBOSITY_LEVEL 3 CACHE STRING "IWYU verbosity level (the higher the level, the more output)") set(IWYU_VERBOSITY_LEVEL 3 CACHE STRING "IWYU verbosity level (the higher the level, the more output)")
macro(_find_iwyu)
find_program(_iwyu_path NAMES "include-what-you-use")
if(NOT _iwyu_path)
message(WARNING "'include-what-you-use' executable not found!")
return()
endif()
endmacro()
macro(_iwyu_args_append arg) macro(_iwyu_args_append arg)
list(APPEND _iwyu_args "-Xiwyu" "${arg}") list(APPEND _iwyu_args "-Xiwyu" "${arg}")
endmacro() endmacro()
macro(_iwyu_args_append_if_present option arg) macro(_iwyu_args_append_if_present option arg)
if(_set_iwyu_${option}) if(_enable_iwyu_${option})
_iwyu_args_append("${arg}") _iwyu_args_append("${arg}")
endif() endif()
endmacro() endmacro()
macro(_process_iwyu_arguments offset) macro(_enable_iwyu_failed log_postfix)
set(_options NO_DEFAULT_MAPPINGS PCH_IN_CODE TRANSITIVE_INCLUDES_ONLY NO_COMMENTS NO_FORWARD_DECLARATIONS CXX17_NAMESPACES QUOTED_INCLUDES_FIRST) if(NOT _enable_iwyu_QUIET)
set(_one_value_args MAPPING_FILE MAX_LINE_LENGTH) message(STATUS "Enabling include-what-you-use${log_postfix} - failed")
endif()
return()
endmacro()
macro(_process_iwyu_arguments offset log_postfix)
set(_options QUIET REQUIRED NO_DEFAULT_MAPPINGS PCH_IN_CODE TRANSITIVE_INCLUDES_ONLY NO_COMMENTS NO_FORWARD_DECLARATIONS CXX17_NAMESPACES QUOTED_INCLUDES_FIRST)
set(_one_value_args PROGRAM MAPPING_FILE MAX_LINE_LENGTH)
set(_multi_value_args KEEP) set(_multi_value_args KEEP)
cmake_parse_arguments(PARSE_ARGV ${offset} _set_iwyu "${_options}" "${_one_value_args}" "${_multi_value_args}") cmake_parse_arguments(PARSE_ARGV ${offset} _enable_iwyu "${_options}" "${_one_value_args}" "${_multi_value_args}")
# validate and process arguments # validate and process arguments
if(${prefix}_UNPARSED_ARGUMENTS) if(_enable_iwyu_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Invalid arguments '${${prefix}_UNPARSED_ARGUMENTS}'") message(FATAL_ERROR "Invalid arguments '${_enable_iwyu_UNPARSED_ARGUMENTS}'")
endif() endif()
if(_set_iwyu_KEEP) if(_enable_iwyu_KEYWORDS_MISSING_VALUES)
foreach(_pattern ${_set_iwyu_KEEP}) message(FATAL_ERROR "No value provided for '${_enable_iwyu_KEYWORDS_MISSING_VALUES}'")
endif()
if(NOT _enable_iwyu_QUIET)
message(STATUS "Enabling include-what-you-use${log_postfix}")
endif()
if(${_enable_iwyu_REQUIRED})
set(_error_log_level FATAL_ERROR)
elseif(NOT _enable_iwyu_QUIET)
set(_error_log_level STATUS)
endif()
if(NOT DEFINED _enable_iwyu_PROGRAM)
set(_enable_iwyu_PROGRAM include-what-you-use)
endif()
find_program(IWYU_PATH ${_enable_iwyu_PROGRAM})
if(IWYU_PATH)
if(NOT _enable_iwyu_QUIET)
message(STATUS " Executable: ${IWYU_PATH}")
endif()
else()
if(DEFINED _error_log_level)
message(${_error_log_level} " '${_enable_iwyu_PROGRAM}' executable was not found")
endif()
_enable_iwyu_failed("${log_postfix}")
endif()
if(_enable_iwyu_KEEP)
foreach(_pattern ${_enable_iwyu_KEEP})
_iwyu_args_append("--keep=${_pattern}") _iwyu_args_append("--keep=${_pattern}")
endforeach() endforeach()
endif() endif()
if(_set_iwyu_MAPPING_FILE) if(_enable_iwyu_MAPPING_FILE)
if(NOT EXISTS ${_set_iwyu_MAPPING_FILE}) if(NOT EXISTS ${_enable_iwyu_MAPPING_FILE})
message(FATAL_ERROR "IWYU: Mapping file '${_set_iwyu_MAPPING_FILE}' does not exist") message(FATAL_ERROR "IWYU: Mapping file '${_enable_iwyu_MAPPING_FILE}' does not exist")
endif() endif()
_iwyu_args_append("--mapping_file=${_set_iwyu_MAPPING_FILE}") _iwyu_args_append("--mapping_file=${_enable_iwyu_MAPPING_FILE}")
endif() endif()
if(_set_iwyu_MAX_LINE_LENGTH) if(_enable_iwyu_MAX_LINE_LENGTH)
if(NOT _set_iwyu_MAX_LINE_LENGTH GREATER 0) if(NOT _enable_iwyu_MAX_LINE_LENGTH GREATER 0)
message(FATAL_ERROR "IWYU: Invalid MAX_LINE_LENGTH value = '${_set_iwyu_MAX_LINE_LENGTH}") message(FATAL_ERROR "IWYU: Invalid MAX_LINE_LENGTH value = '${_enable_iwyu_MAX_LINE_LENGTH}")
endif() endif()
_iwyu_args_append("--max_line_length=${_set_iwyu_MAX_LINE_LENGTH}") _iwyu_args_append("--max_line_length=${_enable_iwyu_MAX_LINE_LENGTH}")
endif() endif()
_iwyu_args_append_if_present(NO_DEFAULT_MAPPINGS "--no_default_mappings") _iwyu_args_append_if_present(NO_DEFAULT_MAPPINGS "--no_default_mappings")
@@ -88,10 +117,36 @@ macro(_process_iwyu_arguments offset)
_iwyu_args_append_if_present(QUOTED_INCLUDES_FIRST "--quoted_includes_first") _iwyu_args_append_if_present(QUOTED_INCLUDES_FIRST "--quoted_includes_first")
_iwyu_args_append("--verbose=${IWYU_VERBOSITY_LEVEL}") _iwyu_args_append("--verbose=${IWYU_VERBOSITY_LEVEL}")
if(NOT _enable_iwyu_QUIET)
message(STATUS " Arguments: ${_iwyu_args}")
message(STATUS "Enabling include-what-you-use${log_postfix} - done")
endif()
endmacro() endmacro()
# #
# set_target_iwyu(TargetName # enable_iwyu([PROGRAM] # include-what-you-use by default
# [QUIET] [REQUIRED]
# [KEEP patterns...]
# [MAPPING_FILE file]
# [NO_DEFAULT_MAPPINGS]
# [PCH_IN_CODE]
# [TRANSITIVE_INCLUDES_ONLY]
# [MAX_LINE_LENGTH length]
# [NO_COMMENTS]
# [NO_FORWARD_DECLARATIONS]
# [CXX17_NAMESPACES]
# [QUOTED_INCLUDES_FIRST])
#
function(enable_iwyu)
_process_iwyu_arguments(0 "")
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "${_iwyu_path};${_iwyu_args}" PARENT_SCOPE)
endfunction()
#
# enable_target_iwyu(TargetName
# [PROGRAM] # include-what-you-use by default
# [QUIET] [REQUIRED]
# [KEEP pattern...] # [KEEP pattern...]
# [MAPPING_FILE file] # [MAPPING_FILE file]
# [NO_DEFAULT_MAPPINGS] # [NO_DEFAULT_MAPPINGS]
@@ -103,40 +158,9 @@ endmacro()
# [CXX17_NAMESPACES] # [CXX17_NAMESPACES]
# [QUOTED_INCLUDES_FIRST]) # [QUOTED_INCLUDES_FIRST])
# #
function(set_target_iwyu target) function(enable_target_iwyu target)
_find_iwyu() _process_iwyu_arguments(1 " for '${target}'")
_process_iwyu_arguments(1)
message(STATUS "Setting include-what-you-use for '${target}'")
message(STATUS " Path: ${_iwyu_path}")
message(STATUS " Arguments: ${_iwyu_args}")
message(STATUS "Setting include-what-you-use for '${target}' - done")
set_target_properties(${target} PROPERTIES set_target_properties(${target} PROPERTIES
CXX_INCLUDE_WHAT_YOU_USE "${_iwyu_path};${_iwyu_args}" CXX_INCLUDE_WHAT_YOU_USE "${_iwyu_path};${_iwyu_args}"
) )
endfunction() endfunction()
#
# set_target_iwyu([KEEP patterns...]
# [MAPPING_FILE file]
# [NO_DEFAULT_MAPPINGS]
# [PCH_IN_CODE]
# [TRANSITIVE_INCLUDES_ONLY]
# [MAX_LINE_LENGTH length]
# [NO_COMMENTS]
# [NO_FORWARD_DECLARATIONS]
# [CXX17_NAMESPACES]
# [QUOTED_INCLUDES_FIRST])
#
function(set_iwyu)
_find_iwyu()
_process_iwyu_arguments(0)
message(STATUS "Setting include-what-you-use")
message(STATUS " Path: ${_iwyu_path}")
message(STATUS " Arguments: ${_iwyu_args}")
message(STATUS "Setting include-what-you-use - done")
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "${_iwyu_path};${_iwyu_args}" PARENT_SCOPE)
endfunction()

View File

@@ -0,0 +1,31 @@
# 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.4)
function(ensure_entry_point)
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
message(FATAL_ERROR "'${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt' is meant to be used only "
"as a CMake entry point and should not be included from other CMake files. "
"Include '${CMAKE_CURRENT_SOURCE_DIR}/src/CMaskeLists.txt' directly instead.")
endif()
endfunction()

View File

@@ -22,7 +22,7 @@
# Based on https://github.com/lefticus/cpp_starter_project/blob/master/cmake/CompilerWarnings.cmake # Based on https://github.com/lefticus/cpp_starter_project/blob/master/cmake/CompilerWarnings.cmake
cmake_minimum_required(VERSION 3.3) cmake_minimum_required(VERSION 3.15)
option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" ON) option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" ON)
@@ -90,8 +90,6 @@ macro(_set_flags)
endif() endif()
if(MSVC) if(MSVC)
string(REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE)
set(flags ${MSVC_WARNINGS}) set(flags ${MSVC_WARNINGS})
elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
set(flags ${CLANG_WARNINGS}) set(flags ${CLANG_WARNINGS})

View File

@@ -22,7 +22,7 @@
from conans import ConanFile, tools from conans import ConanFile, tools
from conans.tools import Version, check_min_cppstd from conans.tools import Version, check_min_cppstd
from conan.tools.cmake import CMakeToolchain, CMake, CMakeDeps from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake
from conans.errors import ConanInvalidConfiguration from conans.errors import ConanInvalidConfiguration
import os, re import os, re
@@ -58,28 +58,27 @@ class UnitsConan(ConanFile):
# } # }
generators = "cmake_paths" generators = "cmake_paths"
_cmake = None
@property @property
def _run_tests(self): def _run_tests(self):
return tools.get_env("CONAN_RUN_TESTS", False) return tools.get_env("CONAN_RUN_TESTS", False)
def _configure_cmake(self):
if not self._cmake:
self._cmake = CMake(self)
if self._run_tests:
# developer's mode (unit tests, examples, documentation, restrictive compilation warnings, ...)
self._cmake.configure()
else:
# consumer's mode (library sources only)
self._cmake.configure(source_folder="src")
return self._cmake
def set_version(self): def set_version(self):
content = tools.load(os.path.join(self.recipe_folder, "src/CMakeLists.txt")) content = tools.load(os.path.join(self.recipe_folder, "src/CMakeLists.txt"))
version = re.search(r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content).group(1) version = re.search(r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content).group(1)
self.version = version.strip() self.version = version.strip()
def requirements(self):
compiler = self.settings.compiler
if compiler == "clang" and compiler.libcxx == "libc++":
self.requires("range-v3/0.11.0")
def build_requirements(self):
if self._run_tests:
self.build_requires("catch2/2.13.4")
self.build_requires("linear_algebra/0.7.1@conan-oss/stable")
if self.options.build_docs:
self.build_requires("doxygen/1.9.1")
def validate(self): def validate(self):
compiler = self.settings.compiler compiler = self.settings.compiler
version = Version(self.settings.compiler.version) version = Version(self.settings.compiler.version)
@@ -102,20 +101,8 @@ class UnitsConan(ConanFile):
# # build_docs has sense only in a development or CI build # # build_docs has sense only in a development or CI build
# del self.options.build_docs # del self.options.build_docs
def requirements(self):
compiler = self.settings.compiler
if compiler == "clang" and compiler.libcxx == "libc++":
self.requires("range-v3/0.11.0")
def build_requirements(self):
if self._run_tests:
self.build_requires("catch2/2.13.4")
self.build_requires("linear_algebra/0.7.0@public-conan/stable")
if self.options.build_docs:
self.build_requires("doxygen/1.8.20")
def generate(self): def generate(self):
tc = CMakeToolchain(self) tc = CMakeToolchain(self, generator=os.getenv("CONAN_CMAKE_GENERATOR"))
tc.variables["UNITS_DOWNCAST_MODE"] = str(self.options.downcast_mode).upper() tc.variables["UNITS_DOWNCAST_MODE"] = str(self.options.downcast_mode).upper()
# if self._run_tests: # TODO Enable this when environment is supported in the Conan toolchain # if self._run_tests: # TODO Enable this when environment is supported in the Conan toolchain
tc.variables["UNITS_BUILD_DOCS"] = self.options.build_docs tc.variables["UNITS_BUILD_DOCS"] = self.options.build_docs
@@ -124,14 +111,16 @@ class UnitsConan(ConanFile):
deps.generate() deps.generate()
def build(self): def build(self):
cmake = self._configure_cmake() cmake = CMake(self)
cmake.configure(source_folder=None if self._run_tests else "src")
cmake.build() cmake.build()
if self._run_tests: if self._run_tests:
cmake.test(output_on_failure=True) cmake.test(output_on_failure=True)
def package(self): def package(self):
self.copy(pattern="LICENSE.md", dst="licenses") self.copy(pattern="LICENSE.md", dst="licenses")
cmake = self._configure_cmake() cmake = CMake(self)
cmake.configure(source_folder=None if self._run_tests else "src")
cmake.install() cmake.install()
def package_id(self): def package_id(self):

View File

@@ -1,12 +1,19 @@
# Release notes # Release notes
- **0.7.0 WIP** - **0.8.0 WIP**
- (!) fix: add `quantity_point::origin`, like `std::chrono::time_point::clock`
- fix: account for different dimensions in `quantity_point_cast`'s constraint
- build: doxygen updated to 1.9.1
- build: linear_algebra updated to 0.7.1
- **0.7.0 May 11, 2021**
- (!) refactor: `ScalableNumber` renamed to `Representation` - (!) refactor: `ScalableNumber` renamed to `Representation`
- (!) refactor: output stream operators moved to the `units/quantity_io.h` header file - (!) refactor: output stream operators moved to the `units/quantity_io.h` header file
- (!) refactor: Refactored the library file tree - (!) refactor: Refactored the library file tree
- (!) refactor: `quantity::count()` renamed to `quantity::number()` - (!) refactor: `quantity::count()` renamed to `quantity::number()`
- (!) refactor: `data` system renamed to `isq::iec80000` (quantity names renamed too) - (!) refactor: `data` system renamed to `isq::iec80000` (quantity names renamed too)
- (!) refactor: quantity UDLs support has to be enabled with `UNITS_LITERALS` preprocessor define - (!) refactor: `*deduced_unit` renamed to `*derived_unit`
- (!) refactor: got rid of a `noble_derived_unit`
- refactor: quantity (kind) point updated to reflect latest changes to `quantity` - refactor: quantity (kind) point updated to reflect latest changes to `quantity`
- refactor: basic concepts, `quantity` and `quantity_cast` refactored - refactor: basic concepts, `quantity` and `quantity_cast` refactored
- refactor: `abs()` definition refactored to be more explicit about the return type - refactor: `abs()` definition refactored to be more explicit about the return type
@@ -17,12 +24,15 @@
- feat: CTAD for dimensionless quantity added - feat: CTAD for dimensionless quantity added
- feat: `modulation_rate` support added (thanks [@go2sh](https://github.com/go2sh)) - feat: `modulation_rate` support added (thanks [@go2sh](https://github.com/go2sh))
- feat: SI prefixes for `isq::iec80000` support added (thanks [@go2sh](https://github.com/go2sh)) - feat: SI prefixes for `isq::iec80000` support added (thanks [@go2sh](https://github.com/go2sh))
- feat: a possibility to disable quantity UDLs support with `UNITS_NO_LITERALS` preprocessor define
- feat: a support to define ISQ derived dimensions in terms of different number or order of components
- perf: preconditions check do not influence the runtime performance of a Release build - perf: preconditions check do not influence the runtime performance of a Release build
- perf: `quantity_cast()` generates less assembly instructions - perf: `quantity_cast()` generates less assembly instructions
- perf: temporary string creation removed from `quantity::op<<()` - perf: temporary string creation removed from `quantity::op<<()`
- perf: value initialization for quantity value removed (left with a default initialization) - perf: value initialization for quantity value removed (left with a default initialization)
- perf: limited the `equivalent` trait usage - perf: limited the `equivalent` trait usage
- perf: limited the C++ Standard Library headers usage - perf: limited the C++ Standard Library headers usage
- perf: rvalue references support added for constructors and getters
- (!) fix: `exp()` has sense only for dimensionless quantities - (!) fix: `exp()` has sense only for dimensionless quantities
- (!) fix: `dim_torque` now properly divides by an angle (instead of multiply) + default unit name change - (!) fix: `dim_torque` now properly divides by an angle (instead of multiply) + default unit name change
- fix: quantity's operators fixed to behave like the underlying types do - fix: quantity's operators fixed to behave like the underlying types do
@@ -30,7 +40,10 @@
- fix: ambiguous case for empty type list resolved - fix: ambiguous case for empty type list resolved
- fix: downcasting facility for non-default-constructible types - fix: downcasting facility for non-default-constructible types
- fix: restore user-warnings within the library implementation - fix: restore user-warnings within the library implementation
- fix: the text symbol of `foot_pound_force` and `foot_pound_force_per_second`
- fix: quantity modulo arithmetics fixed
- (!) build: Conan testing version is now hosted on [Artifactory](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units) - (!) build: Conan testing version is now hosted on [Artifactory](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units)
- (!) build: Linear Algebra is now hosted on its [Artifactory](https://twonington.jfrog.io/artifactory/api/conan/conan-oss)
- (!) build: `BUILD_DOCS` CMake option renamed to `UNITS_BUILD_DOCS` - (!) build: `BUILD_DOCS` CMake option renamed to `UNITS_BUILD_DOCS`
- build: doxygen updated to 1.8.20 - build: doxygen updated to 1.8.20
- build: catch2 updated to 2.13.4 - build: catch2 updated to 2.13.4
@@ -39,6 +52,7 @@
- build: Conan generator switched to `cmake_find_package_multi` - build: Conan generator switched to `cmake_find_package_multi`
- build: Conan CMakeToolchain support added - build: Conan CMakeToolchain support added
- build: CMake scripts cleanup - build: CMake scripts cleanup
- build: ccache support added
- ci: CI switched from Travis CI to GitHub Actions - ci: CI switched from Travis CI to GitHub Actions
- **0.6.0 September 13, 2020** - **0.6.0 September 13, 2020**

View File

@@ -91,15 +91,3 @@ WARN_AS_ERROR = NO
# The default value is: NO. # The default value is: NO.
QUIET = YES QUIET = YES
# The PREDEFINED tag can be used to specify one or more macro names that are
# defined before the preprocessor is started (similar to the -D option of e.g.
# gcc). The argument of the tag is a list of macros of the form: name or
# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
# is assumed. To prevent a macro definition from being undefined via #undef or
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = UNITS_REFERENCES \
UNITS_LITERALS \
UNITS_ALIASES

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 54 KiB

View File

@@ -1,7 +1,7 @@
avg_speed avg_speed
========= =========
.. literalinclude:: ../../example/references/avg_speed.cpp .. literalinclude:: ../../../example/references/avg_speed.cpp
:caption: avg_speed.cpp :caption: avg_speed.cpp
:start-at: #include :start-at: #include
:linenos: :linenos:

View File

@@ -1,7 +1,7 @@
box_example box_example
=========== ===========
.. literalinclude:: ../../example/references/box_example.cpp .. literalinclude:: ../../../example/references/box_example.cpp
:caption: box_example.cpp :caption: box_example.cpp
:start-at: #include :start-at: #include
:linenos: :linenos:

View File

@@ -1,7 +1,7 @@
capacitor_time_curve capacitor_time_curve
==================== ====================
.. literalinclude:: ../../example/references/capacitor_time_curve.cpp .. literalinclude:: ../../../example/references/capacitor_time_curve.cpp
:caption: capacitor_time_curve.cpp :caption: capacitor_time_curve.cpp
:start-at: #include :start-at: #include
:linenos: :linenos:

View File

@@ -1,7 +1,7 @@
clcpp_response clcpp_response
============== ==============
.. literalinclude:: ../../example/references/clcpp_response.cpp .. literalinclude:: ../../../example/references/clcpp_response.cpp
:caption: clcpp_response.cpp :caption: clcpp_response.cpp
:start-at: #include :start-at: #include
:linenos: :linenos:

View File

@@ -1,7 +1,7 @@
experimental_angle experimental_angle
================== ==================
.. literalinclude:: ../../example/references/experimental_angle.cpp .. literalinclude:: ../../../example/references/experimental_angle.cpp
:caption: experimental_angle.cpp :caption: experimental_angle.cpp
:start-at: #include :start-at: #include
:linenos: :linenos:

View File

@@ -1,7 +1,7 @@
foot_pound_second foot_pound_second
================= =================
.. literalinclude:: ../../example/references/foot_pound_second.cpp .. literalinclude:: ../../../example/references/foot_pound_second.cpp
:caption: foot_pound_second.cpp :caption: foot_pound_second.cpp
:start-at: #include :start-at: #include
:linenos: :linenos:

View File

@@ -13,7 +13,7 @@ This example presents the usage of:
- quantities text output formatting, - quantities text output formatting,
- cooperation with `std::chrono`. - cooperation with `std::chrono`.
.. literalinclude:: ../../example/glide_computer/include/glide_computer.h .. literalinclude:: ../../../example/glide_computer/include/glide_computer.h
:caption: glide_computer.h :caption: glide_computer.h
:start-at: #include :start-at: #include
:end-before: using namespace units; :end-before: using namespace units;
@@ -35,7 +35,7 @@ For example we have 3 for a quantity of length:
- ``height`` - a relative altitude difference between 2 points in the air - ``height`` - a relative altitude difference between 2 points in the air
- ``altitude`` - an absolute altitude value measured form the mean sea level (AMSL). - ``altitude`` - an absolute altitude value measured form the mean sea level (AMSL).
.. literalinclude:: ../../example/glide_computer/include/glide_computer.h .. literalinclude:: ../../../example/glide_computer/include/glide_computer.h
:caption: glide_computer.h :caption: glide_computer.h
:start-at: using namespace units; :start-at: using namespace units;
:end-before: // text output :end-before: // text output
@@ -44,7 +44,7 @@ For example we have 3 for a quantity of length:
Next a custom text output is provided both for C++ output streams and the text formatting facility. Next a custom text output is provided both for C++ output streams and the text formatting facility.
.. literalinclude:: ../../example/glide_computer/include/glide_computer.h .. literalinclude:: ../../../example/glide_computer/include/glide_computer.h
:caption: glide_computer.h :caption: glide_computer.h
:start-at: // text output :start-at: // text output
:end-before: // definition of glide computer databases and utilities :end-before: // definition of glide computer databases and utilities
@@ -58,13 +58,13 @@ convert it to the one required by the engine interface.
The glide calculator takes task created as a list of waypoints, glider performance data, weather conditions, The glide calculator takes task created as a list of waypoints, glider performance data, weather conditions,
safety constraints, and a towing height. safety constraints, and a towing height.
.. literalinclude:: ../../example/glide_computer/include/glide_computer.h .. literalinclude:: ../../../example/glide_computer/include/glide_computer.h
:caption: glide_computer.h :caption: glide_computer.h
:start-at: // definition of glide computer databases and utilities :start-at: // definition of glide computer databases and utilities
:linenos: :linenos:
:lineno-match: :lineno-match:
.. literalinclude:: ../../example/references/glide_computer_example.cpp .. literalinclude:: ../../../example/references/glide_computer_example.cpp
:caption: glide_computer_example.cpp :caption: glide_computer_example.cpp
:start-at: #include :start-at: #include
:linenos: :linenos:
@@ -74,7 +74,7 @@ Having all of that it estimates the number of flight phases (towing, circling, g
needed to finish a task. As an output it provides the duration needed to finish the task while needed to finish a task. As an output it provides the duration needed to finish the task while
flying a selected glider in the specific weather conditions. flying a selected glider in the specific weather conditions.
.. literalinclude:: ../../example/glide_computer/glide_computer.cpp .. literalinclude:: ../../../example/glide_computer/glide_computer.cpp
:caption: glide_computer.cpp :caption: glide_computer.cpp
:start-at: #include :start-at: #include
:linenos: :linenos:

View File

@@ -1,7 +1,7 @@
hello_units hello_units
=========== ===========
.. literalinclude:: ../../example/hello_units.cpp .. literalinclude:: ../../../example/hello_units.cpp
:caption: hello_units.cpp :caption: hello_units.cpp
:start-at: #include :start-at: #include
:linenos: :linenos:

View File

@@ -1,7 +1,7 @@
total_energy total_energy
============ ============
.. literalinclude:: ../../example/references/total_energy.cpp .. literalinclude:: ../../../example/references/total_energy.cpp
:caption: total_energy.cpp :caption: total_energy.cpp
:start-at: #include :start-at: #include
:linenos: :linenos:

View File

@@ -1,7 +1,7 @@
unknown_dimension unknown_dimension
================= =================
.. literalinclude:: ../../example/references/unknown_dimension.cpp .. literalinclude:: ../../../example/references/unknown_dimension.cpp
:caption: unknown_dimension.cpp :caption: unknown_dimension.cpp
:start-at: #include :start-at: #include
:linenos: :linenos:

View File

@@ -1,7 +1,7 @@
linear_algebra linear_algebra
============== ==============
.. literalinclude:: ../../example/references/linear_algebra.cpp .. literalinclude:: ../../../example/references/linear_algebra.cpp
:caption: linear_algebra.cpp :caption: linear_algebra.cpp
:start-at: #include :start-at: #include
:linenos: :linenos:

View File

@@ -1,7 +1,7 @@
measurement measurement
=========== ===========
.. literalinclude:: ../../example/measurement.cpp .. literalinclude:: ../../../example/measurement.cpp
:caption: measurement.cpp :caption: measurement.cpp
:start-at: #include :start-at: #include
:linenos: :linenos:

View File

@@ -1,7 +1,7 @@
custom_systems custom_systems
============== ==============
.. literalinclude:: ../../example/custom_systems.cpp .. literalinclude:: ../../../example/custom_systems.cpp
:caption: custom_systems.cpp :caption: custom_systems.cpp
:start-at: #include :start-at: #include
:linenos: :linenos:

View File

@@ -1,7 +1,7 @@
conversion_factor conversion_factor
================= =================
.. literalinclude:: ../../example/conversion_factor.cpp .. literalinclude:: ../../../example/conversion_factor.cpp
:caption: conversion_factor.cpp :caption: conversion_factor.cpp
:start-at: #include :start-at: #include
:linenos: :linenos:

View File

@@ -23,7 +23,7 @@ The most important concepts in the library are `Unit`, `Dimension`,
] ]
[<abstract>QuantityPoint| [<abstract>QuantityPoint|
[quantity_point<Dimension, Unit, Rep>] [quantity_point<PointOrigin, Unit, Rep>]
] ]
[<abstract>QuantityKind| [<abstract>QuantityKind|
@@ -39,6 +39,10 @@ The most important concepts in the library are `Unit`, `Dimension`,
[Unit]<-[Quantity] [Unit]<-[Quantity]
[Quantity]<-[QuantityPoint] [Quantity]<-[QuantityPoint]
[<abstract>PointOrigin]<-[QuantityPoint]
[Dimension]<-[PointOrigin]
[PointOrigin]<-[PointKind]
[<abstract>Kind]<-[QuantityKind] [<abstract>Kind]<-[QuantityKind]
[Dimension]<-[Kind] [Dimension]<-[Kind]
[Quantity]<-[QuantityKind] [Quantity]<-[QuantityKind]
@@ -60,7 +64,7 @@ derived dimensions. Examples: ``si::dim_time``, ``si::dim_length``, ``si::dim_sp
specific representation. Examples: ``quantity<si::dim_time, si::second, int>``, specific representation. Examples: ``quantity<si::dim_time, si::second, int>``,
``si::length<si::metre, int>``, ``si::speed<si::kilometre_per_hour>``. ``si::length<si::metre, int>``, ``si::speed<si::kilometre_per_hour>``.
`QuantityPoint` is an absolute `Quantity` with respect to some origin. `QuantityPoint` is an absolute `Quantity` with respect to an origin.
Examples: timestamp (as opposed to duration), absolute temperature Examples: timestamp (as opposed to duration), absolute temperature
(as opposed to temperature difference). (as opposed to temperature difference).
@@ -68,6 +72,6 @@ Examples: timestamp (as opposed to duration), absolute temperature
distance (``horizonal_kind``) and height (``vertical_kind``) are different kinds distance (``horizonal_kind``) and height (``vertical_kind``) are different kinds
of a length quantity. of a length quantity.
`QuantityPointKind` is an absolute `QuantityKind` with respect to some origin. `QuantityPointKind` is an absolute `QuantityKind` with respect to an origin.
Examples: altitude is a quantity point of ``vertical_kind`` (as opposed to Examples: altitude is a quantity point of ``vertical_kind`` (as opposed to
height). height).

View File

@@ -77,7 +77,7 @@ you can use a quantity argument instead of a quantity kind.
:emphasize-lines: 8-9 :emphasize-lines: 8-9
struct height_kind : kind<height_kind, dim_length> {}; struct height_kind : kind<height_kind, dim_length> {};
struct rate_of_climb_kind : derived_kind<rate_of_climb_kind, height_kind, dim_speed> {}; struct rate_of_climb_kind : derived_kind<rate_of_climb_kind, dim_speed, height_kind> {};
template <Unit U, Representation Rep = double> using height = quantity_kind<height_kind, U, Rep>; template <Unit U, Representation Rep = double> using height = quantity_kind<height_kind, U, Rep>;
template <Unit U, Representation Rep = double> using rate_of_climb = quantity_kind<rate_of_climb_kind, U, Rep>; template <Unit U, Representation Rep = double> using rate_of_climb = quantity_kind<rate_of_climb_kind, U, Rep>;
@@ -90,7 +90,7 @@ you can use a quantity argument instead of a quantity kind.
:emphasize-lines: 8-12 :emphasize-lines: 8-12
struct width_kind : kind<width_kind, dim_length> {}; struct width_kind : kind<width_kind, dim_length> {};
struct horizontal_area_kind : derived_kind<horizontal_area_kind, width_kind, dim_area> {}; struct horizontal_area_kind : derived_kind<horizontal_area_kind, dim_area, width_kind> {};
template <Unit U, Representation Rep = double> using width = quantity_kind<width_kind, U, Rep>; template <Unit U, Representation Rep = double> using width = quantity_kind<width_kind, U, Rep>;
template <Unit U, Representation Rep = double> using horizontal_area = quantity_kind<horizontal_area_kind, U, Rep>; template <Unit U, Representation Rep = double> using horizontal_area = quantity_kind<horizontal_area_kind, U, Rep>;
@@ -106,8 +106,9 @@ Quantity Points
+++++++++++++++ +++++++++++++++
Quantity points have a more restricted set of operations. Quantity points have a more restricted set of operations.
Quantity can be added to or subtracted from a quantity point. Quantity can be added to or subtracted
The result will always be a quantity point of the same dimension: from a quantity point of the same origin.
The result will always be a quantity point of the same origin:
.. code-block:: .. code-block::
:emphasize-lines: 3-5 :emphasize-lines: 3-5
@@ -132,9 +133,10 @@ The result is a relative quantity of the same dimension:
It is not allowed to: It is not allowed to:
- add quantity points - add quantity points,
- subtract a quantity point from a quantity: - subtract a quantity point from a quantity,
- multiply nor divide quantity points with anything else. - multiply nor divide quantity points with anything else, and
- mix quantity points with different origins:
.. code-block:: .. code-block::
:emphasize-lines: 3-5 :emphasize-lines: 3-5
@@ -144,6 +146,8 @@ The result is a relative quantity of the same dimension:
auto res1 = quantity_point{dist1} + quantity_point{dist2}; // ERROR auto res1 = quantity_point{dist1} + quantity_point{dist2}; // ERROR
auto res2 = dist1 - quantity_point{dist2}; // ERROR auto res2 = dist1 - quantity_point{dist2}; // ERROR
auto res3 = quantity_point{dist1} / (2 * s); // ERROR auto res3 = quantity_point{dist1} / (2 * s); // ERROR
auto res4 = quantity_point{std::chrono::utc_second{1s}} +
quantity_point{std::chrono::sys_second{1s}}; // ERROR
Quantity Point Kinds Quantity Point Kinds
++++++++++++++++++++ ++++++++++++++++++++

View File

@@ -70,7 +70,7 @@ Unit-Specific Aliases (Experimental)
Additionally to the dimension-specific aliases there are also ones provided for Additionally to the dimension-specific aliases there are also ones provided for
each and every :term:`unit` in the library:: each and every :term:`unit` in the library::
#ifdef UNITS_ALIASES #ifndef UNITS_NO_ALIASES
namespace units::aliases::isq::si::inline length { namespace units::aliases::isq::si::inline length {
@@ -86,7 +86,7 @@ each and every :term:`unit` in the library::
} }
#endif // UNITS_ALIASES #endif // UNITS_NO_ALIASES
Using the above our code can look as follows:: Using the above our code can look as follows::
@@ -116,7 +116,7 @@ Quantity References (Experimental)
Quantity References provide an alternative and simplified way to create quantities. Quantity References provide an alternative and simplified way to create quantities.
They are defined using the `reference` class template:: They are defined using the `reference` class template::
#ifdef UNITS_REFERENCES #ifndef UNITS_NO_REFERENCES
namespace length_references { namespace length_references {
@@ -131,7 +131,7 @@ They are defined using the `reference` class template::
} // namespace references } // namespace references
#endif // UNITS_REFERENCES #endif // UNITS_NO_REFERENCES
With the above our code can look as follows:: With the above our code can look as follows::
@@ -157,7 +157,7 @@ User Defined Literals (Experimental)
Alternatively, to construct quantities with compile-time known values the library provides Alternatively, to construct quantities with compile-time known values the library provides
:abbr:`UDL (User Defined Literal)` s for each :term:`unit` of every :term:`dimension`:: :abbr:`UDL (User Defined Literal)` s for each :term:`unit` of every :term:`dimension`::
#ifdef UNITS_LITERALS #ifndef UNITS_NO_LITERALS
inline namespace literals { inline namespace literals {
@@ -169,7 +169,7 @@ Alternatively, to construct quantities with compile-time known values the librar
} }
#endif // UNITS_LITERALS #endif // UNITS_NO_LITERALS
Thanks to them the same code can be as simple as:: Thanks to them the same code can be as simple as::
@@ -186,13 +186,6 @@ Thanks to them the same code can be as simple as::
``d`` (day), ``l`` or ``L`` (litre), ``erg``, ``ergps``). This is why the ``d`` (day), ``l`` or ``L`` (litre), ``erg``, ``ergps``). This is why the
``_q_`` prefix was consistently applied to all the UDLs. ``_q_`` prefix was consistently applied to all the UDLs.
.. important::
As one can read in the next section UDLs, are considered to be inferior to `Quantity References`_
and their definition affects compile-time performance a lot. This is why they are an opt-in feature
of the library and in order to use them one has to provide a `UNITS_LITERALS` preprocessor definition.
UDLs vs Quantity References UDLs vs Quantity References
+++++++++++++++++++++++++++ +++++++++++++++++++++++++++
@@ -473,6 +466,19 @@ Summary
+-----------------------------------------------+-------------+------------+---------------+ +-----------------------------------------------+-------------+------------+---------------+
Don't pay for what you don't use (compile-time performance)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
As noted in the previous chapter, each quantity creation helper has a different impact on the compile-time
performance. Aliases tend to be the fastest to compile but even their definition can be expensive for some
if it is not used in the source code. This is why it is possible to opt-out from each or every quantity
creation helper with the following preprocessor defines::
#define UNITS_NO_ALIASES
#define UNITS_NO_REFERENCES
#define UNITS_NO_LITERALS
Dimension-specific Concepts Dimension-specific Concepts
--------------------------- ---------------------------

View File

@@ -3,9 +3,20 @@
Quantity Points Quantity Points
=============== ===============
A quantity point is an absolute quantity with respect to zero A quantity point is an absolute quantity with respect to an origin
(which represents some origin) and is represented in the library with a and is represented in the library with a `quantity_point` class template.
`quantity_point` class template.
Point Origins
-------------
We need a `point_origin` to represent the origin of a quantity point::
struct mean_sea_level : point_origin<si::dim_length> {};
Quantities points with this origin represent a point from the mean sea level.
The library offers a `dynamic_origin<Dimension>`
for quantity points whose origin is not specified in the type system.
Construction Construction
@@ -14,7 +25,7 @@ Construction
To create the quantity point object from a `quantity` we just have to pass To create the quantity point object from a `quantity` we just have to pass
the value to the `quantity_point` class template explicit constructor:: the value to the `quantity_point` class template explicit constructor::
quantity_point<si::dim_length, si::kilometre, double> d(123 * km); quantity_point<dynamic_origin<si::dim_length>, si::kilometre, double> d(123 * km);
.. note:: .. note::
@@ -25,7 +36,7 @@ the value to the `quantity_point` class template explicit constructor::
`copy initialization <https://en.cppreference.com/w/cpp/language/copy_initialization>`_ `copy initialization <https://en.cppreference.com/w/cpp/language/copy_initialization>`_
**does not compile**:: **does not compile**::
quantity_point<si::dim_length, si::kilometre, double> d = 123 * km; // ERROR quantity_point<dynamic_origin<si::dim_length>, si::kilometre, double> d = 123 * km; // ERROR
Differences To Quantity Differences To Quantity

View File

@@ -8,7 +8,7 @@ compare quantities of the same dimension a notion of a :term:`measurement unit`
was introduced. Units are designated by conventionally assigned names and was introduced. Units are designated by conventionally assigned names and
symbols. Thanks to them it is possible to compare two quantities of the symbols. Thanks to them it is possible to compare two quantities of the
same dimension and express the ratio of the second quantity to the first same dimension and express the ratio of the second quantity to the first
one as a number. For example ``10s`` is ``10`` times more than ``1s``. one as a number. For example ``10 s`` is ``10`` times more than ``1 s``.
Base quantities are expressed in terms of :term:`base units <base unit>` Base quantities are expressed in terms of :term:`base units <base unit>`
(i.e. ``m`` (meter), ``s`` (second)), while derived quantities are expressed (i.e. ``m`` (meter), ``s`` (second)), while derived quantities are expressed
@@ -94,97 +94,14 @@ knows how to convert ``si::metre`` to ``si::centimetre`` and vice versa).
:ref:`use_cases/extensions:Custom Systems` chapter. :ref:`use_cases/extensions:Custom Systems` chapter.
Derived Units
-------------
Derived units can be either named or unnamed.
Derived Named Units
^^^^^^^^^^^^^^^^^^^
Derived named units have a unique symbol (i.e. ``N`` (newton) or ``Pa``
(pascal)) and they are defined in the same way as base units (which
always have to be a named unit)::
namespace si {
struct newton : named_unit<newton, "N", prefix> {};
}
Derived Unnamed Units
^^^^^^^^^^^^^^^^^^^^^
Derived unnamed units are the units where the symbol is derived from the
base quantities symbols and the expression of the dependence of the derived
quantity on the base quantities (i.e. ``m/s`` (metre per second), ````
(square metre)). To support such use cases a library introduced a notion of
:term:`derived dimension recipe` which stores the information about the
order, exponents, and types of dimensions used to defined this particular
derived dimension. For example each of the below ``momentum`` definitions
will result in a different unnamed unit symbol:
.. code-block::
:emphasize-lines: 2-4, 6-8, 10-12
struct dim_momentum : derived_dimension<dim_momentum, kilogram_metre_per_second,
exponent<si::dim_mass, 1>,
exponent<si::dim_length, 1>,
exponent<si::dim_time, -1>> {}; // kg ⋅ m/s
struct dim_momentum : derived_dimension<dim_momentum, kilogram_metre_per_second,
exponent<si::dim_length, 1>,
exponent<si::dim_mass, 1>,
exponent<si::dim_time, -1>> {}; // m ⋅ kg/s
struct dim_momentum : derived_dimension<dim_momentum, kilogram_metre_per_second,
exponent<si::dim_time, -1>,
exponent<si::dim_length, 1>,
exponent<si::dim_mass, 1>> {}; // 1/s ⋅ m ⋅ kg
where ``kilogram_metre_per_second`` is defined as::
struct kilogram_metre_per_second : unit<kilogram_metre_per_second> {};
However, the easiest way to define momentum is just to use the
``si::dim_speed`` derived dimension in the recipe:
.. code-block::
:emphasize-lines: 3
struct dim_momentum : derived_dimension<dim_momentum, kilogram_metre_per_second,
exponent<si::dim_mass, 1>,
exponent<si::dim_speed, 1>> {}; // kg ⋅ m/s
In such a case the library will do its magic and will automatically
unpack a provided derived dimension to its base dimensions in order to
end up with a :term:`normalized derived dimension` for a parent entity.
The need to support a derived dimension in the recipe is not just a
syntactic sugar that allows us to do less typing. It is worth to notice
here that some of the derived unnamed units are defined in terms of other
derived named units (i.e. surface tension quantity is measured in terms
of ``N/m``):
.. code-block::
:emphasize-lines: 2
struct dim_surface_tension : derived_dimension<dim_surface_tension, newton_per_metre,
exponent<si::dim_force, 1>,
exponent<si::dim_length, -1>> {}; // N/m
If we defined the above in terms of base units we would end up with
a ``kg/s²`` derived unit symbol.
Scaled Units Scaled Units
------------ ------------
Until now we talked mostly about Described above base units (in case of base quantities) and
:term:`coherent units <coherent derived unit>` which are units used to :term:`coherent units <coherent derived unit>` (in case of derived quantities),
define dimensions and thus, in their system of units, have proportionality in their system of units, have proportionality factor/ratio equal to one.
factor/ratio equals one. However quantities of each dimension can also use However, quantities of such dimensions can also use units of measurement
other units of measurement to describe their magnitude (numerical value). with other ratios to describe their magnitude (numerical value).
Named Scaled Units Named Scaled Units
@@ -289,13 +206,99 @@ example we can define ``si::kilometre`` as::
as ``km²`` would be invalid). as ``km²`` would be invalid).
Deduced Units Derived Units
^^^^^^^^^^^^^ -------------
:term:`Derived units <derived unit>` are the units used to measure
:term:`derived quantities <derived quantity>`. They can either have their own unique
names (i.e. ``N`` (newton)) or can be composed from the names of units of quantities
used to define thier derived quantity (i.e. ``km/h``).
Derived Named Units
^^^^^^^^^^^^^^^^^^^
Derived named units have a unique symbol (i.e. ``N`` (newton) or ``Pa``
(pascal)) and they are defined in the same way as base units (which
always have to be a named unit)::
namespace si {
struct newton : named_unit<newton, "N", prefix> {};
}
Derived Unnamed Units
^^^^^^^^^^^^^^^^^^^^^
Derived unnamed units are the units where the symbol is derived from the
base quantities symbols and the expression of the dependence of the derived
quantity on the base quantities (i.e. ``m/s`` (metre per second), ````
(square metre)). To support such use cases a library introduced a notion of
:term:`derived dimension recipe` which stores the information about the
order, exponents, and types of dimensions used to define this particular
derived dimension. For example each of the below ``momentum`` definitions
will result in a different unnamed unit symbol:
.. code-block::
:emphasize-lines: 2-4, 6-8, 10-12
struct dim_momentum : derived_dimension<dim_momentum, kilogram_metre_per_second,
exponent<si::dim_mass, 1>,
exponent<si::dim_length, 1>,
exponent<si::dim_time, -1>> {}; // kg ⋅ m/s
struct dim_momentum : derived_dimension<dim_momentum, kilogram_metre_per_second,
exponent<si::dim_length, 1>,
exponent<si::dim_mass, 1>,
exponent<si::dim_time, -1>> {}; // m ⋅ kg/s
struct dim_momentum : derived_dimension<dim_momentum, kilogram_metre_per_second,
exponent<si::dim_time, -1>,
exponent<si::dim_length, 1>,
exponent<si::dim_mass, 1>> {}; // 1/s ⋅ m ⋅ kg
where ``kilogram_metre_per_second`` is defined as::
struct kilogram_metre_per_second : unit<kilogram_metre_per_second> {};
However, the easiest way to define momentum is just to use the
``si::dim_speed`` derived dimension in the recipe:
.. code-block::
:emphasize-lines: 3
struct dim_momentum : derived_dimension<dim_momentum, kilogram_metre_per_second,
exponent<si::dim_mass, 1>,
exponent<si::dim_speed, 1>> {}; // kg ⋅ m/s
In such a case the library will do its magic and will automatically
unpack a provided derived dimension to its base dimensions in order to
end up with a :term:`normalized derived dimension` for a parent entity.
The need to support a derived dimension in the recipe is not just a
syntactic sugar that allows us to do less typing. It is worth to notice
here that some of the derived unnamed units are defined in terms of other
derived named units (i.e. surface tension quantity is measured in terms
of ``N/m``):
.. code-block::
:emphasize-lines: 2
struct dim_surface_tension : derived_dimension<dim_surface_tension, newton_per_metre,
exponent<si::dim_force, 1>,
exponent<si::dim_length, -1>> {}; // N/m
If we defined the above in terms of base units we would end up with
a ``kg/s²`` derived unit symbol.
Derived Scaled Units
^^^^^^^^^^^^^^^^^^^^
For some units determining of a correct scaling ratio may not be trivial, For some units determining of a correct scaling ratio may not be trivial,
and even if done correctly, may be a pain to maintain. For a simple example and even if done correctly, may be a pain to maintain. For a simple example
let's take a "kilometre per hour" unit. What is the easiest to maintain let's take a "kilometre per hour" unit. What is the easiest to maintain
ratio in reference to "metre per second": ratio in reference to the "metre per second":
- ``1000/3600`` - ``1000/3600``
- ``10/36`` - ``10/36``
@@ -303,30 +306,27 @@ ratio in reference to "metre per second":
Whichever, we choose there will always be someone not happy with our choice. Whichever, we choose there will always be someone not happy with our choice.
Thanks to a `deduced_unit` class template provided by the library this problem Thanks to a `derived_unit` class template provided by the library this problem
does not exist at all. With it ``si::kilometre_per_hour`` can be defined as:: does not exist at all. With it ``si::kilometre_per_hour`` can be defined as::
namespace si { namespace si {
struct kilometre_per_hour : deduced_unit<kilometre_per_hour, dim_speed, kilometre, hour> {}; struct kilometre_per_hour : derived_unit<kilometre_per_hour, dim_speed, kilometre, hour> {};
} }
In case the deduced unit should served as a named one we can use ether a In case the scaled derived unit should serve as a named one we can use
`named_deduced_unit` where the user is able to provide a symbol for the unit a `named_derived_unit` where the user is able to provide a symbol for the unit
by him/her-self or `noble_deduced_unit` where the symbol is the deduced name by him/her-self::
based on the ingredients::
namespace si::fps { namespace si::fps {
struct nautical_mile_per_hour : named_deduced_unit<nautical_mile_per_hour, dim_speed, struct knot : named_derived_unit<knot, dim_speed, "knot", no_prefix, nautical_mile, hour> {};
"knot", no_prefix, nautical_mile, hour>{};
struct foot_pound_force : noble_deduced_unit<foot_pound_force, dim_energy, pound_force, foot> {};
} }
Please note that deduced units are the only unit-related class template that Please note that the dervided scaled units are the only unit-related class templates
take a dimension as its parameter. This derived dimension provides a :term:`recipe` that take a dimension as its parameter. This derived dimension provides a :term:`recipe`
used for its definition. Based on the information stored in the recipe used for its definition. Based on the information stored in the recipe
(order, type, and exponents of composite dimensions) and the ratios of units (order, type, and exponents of composite dimensions) and the ratios of units
provided in the template parameter list after the derived dimension parameter, provided in the template parameter list after the derived dimension parameter,
@@ -377,9 +377,8 @@ of a `scaled_unit` class template:
[scaled_unit<UnitRatio, Unit>]<:-[named_unit<Child, Symbol, PrefixFamily>] [scaled_unit<UnitRatio, Unit>]<:-[named_unit<Child, Symbol, PrefixFamily>]
[scaled_unit<UnitRatio, Unit>]<:-[named_scaled_unit<Child, Symbol, PrefixFamily, Ratio, Unit>] [scaled_unit<UnitRatio, Unit>]<:-[named_scaled_unit<Child, Symbol, PrefixFamily, Ratio, Unit>]
[scaled_unit<UnitRatio, Unit>]<:-[prefixed_unit<Child, Prefix, Unit>] [scaled_unit<UnitRatio, Unit>]<:-[prefixed_unit<Child, Prefix, Unit>]
[scaled_unit<UnitRatio, Unit>]<:-[deduced_unit<Child, Dimension, Unit, Unit...>] [scaled_unit<UnitRatio, Unit>]<:-[derived_unit<Child, Dimension, Unit, Unit...>]
[scaled_unit<UnitRatio, Unit>]<:-[noble_deduced_unit<Child, Dimension, Unit, Unit...>] [scaled_unit<UnitRatio, Unit>]<:-[named_derived_unit<Child, Dimension, Symbol, PrefixFamily, Unit, Unit...>]
[scaled_unit<UnitRatio, Unit>]<:-[named_deduced_unit<Child, Dimension, Symbol, PrefixFamily, Unit, Unit...>]
[scaled_unit<UnitRatio, Unit>]<:-[alias_unit<Unit, Symbol, PrefixFamily>] [scaled_unit<UnitRatio, Unit>]<:-[alias_unit<Unit, Symbol, PrefixFamily>]
[scaled_unit<UnitRatio, Unit>]<:-[prefixed_alias_unit<Unit, Prefix, AliasUnit>] [scaled_unit<UnitRatio, Unit>]<:-[prefixed_alias_unit<Unit, Prefix, AliasUnit>]

View File

@@ -3,8 +3,6 @@ Quick Start
Here is a small example of possible operations:: Here is a small example of possible operations::
#define UNITS_REFERENCES
#include <units/isq/si/area.h> #include <units/isq/si/area.h>
#include <units/isq/si/frequency.h> #include <units/isq/si/frequency.h>
#include <units/isq/si/length.h> #include <units/isq/si/length.h>
@@ -34,7 +32,7 @@ Here is a small example of possible operations::
.. admonition:: Try it on Compiler Explorer .. admonition:: Try it on Compiler Explorer
`Example #1 <https://godbolt.org/z/53bTahKd8>`_ `Example #1 <https://godbolt.org/z/5dvY8Woh1>`_
This library requires some C++20 features (concepts, classes as This library requires some C++20 features (concepts, classes as
:abbr:`NTTP (Non-Type Template Parameter)`, ...). Thanks to them the user gets a powerful :abbr:`NTTP (Non-Type Template Parameter)`, ...). Thanks to them the user gets a powerful
@@ -42,10 +40,6 @@ but still easy to use interface where all unit conversions and dimensional analy
performed without sacrificing on accuracy. Please see the below example for a quick preview performed without sacrificing on accuracy. Please see the below example for a quick preview
of basic library features:: of basic library features::
#define UNITS_ALIASES
#define UNITS_LITERALS
#define UNITS_REFERENCES
#include <units/format.h> #include <units/format.h>
#include <units/isq/si/international/length.h> #include <units/isq/si/international/length.h>
#include <units/isq/si/international/speed.h> #include <units/isq/si/international/speed.h>
@@ -92,7 +86,7 @@ of basic library features::
.. admonition:: Try it on Compiler Explorer .. admonition:: Try it on Compiler Explorer
`Example #2 <https://godbolt.org/z/jKnPPPEx6>`_ `Example #2 <https://godbolt.org/z/9fnzfbhb6>`_
.. seealso:: .. seealso::

View File

@@ -16,13 +16,10 @@ Units
.. doxygenstruct:: units::prefixed_unit .. doxygenstruct:: units::prefixed_unit
:members: :members:
.. doxygenstruct:: units::deduced_unit .. doxygenstruct:: units::derived_unit
:members: :members:
.. doxygenstruct:: units::noble_deduced_unit .. doxygenstruct:: units::named_derived_unit
:members:
.. doxygenstruct:: units::named_deduced_unit
:members: :members:
.. doxygenstruct:: units::alias_unit .. doxygenstruct:: units::alias_unit

View File

@@ -92,7 +92,6 @@ in *~/.conan/profiles* directory. An example profile can look as follows:
[env] [env]
CC=/usr/bin/gcc-10 CC=/usr/bin/gcc-10
CXX=/usr/bin/g++-10 CXX=/usr/bin/g++-10
CONAN_CMAKE_GENERATOR=Ninja
.. tip:: .. tip::
@@ -248,7 +247,7 @@ library release the following steps may be performed:
:caption: conanfile.txt :caption: conanfile.txt
[requires] [requires]
mp-units/0.6.0 mp-units/0.7.0
[generators] [generators]
CMakeToolchain CMakeToolchain
@@ -279,7 +278,7 @@ library release the following steps may be performed:
.. code-block:: shell .. code-block:: shell
mkdir build && cd build mkdir my_project/build && cd my_project/build
conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -b=missing conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -b=missing
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
cmake --build . cmake --build .
@@ -314,7 +313,7 @@ differences:
:caption: conanfile.txt :caption: conanfile.txt
[requires] [requires]
mp-units/0.7.0@mpusz/testing mp-units/0.8.0@mpusz/testing
[generators] [generators]
CMakeToolchain CMakeToolchain
@@ -330,12 +329,27 @@ differences:
.. code-block:: shell .. code-block:: shell
mkdir build && cd build mkdir my_project/build && cd my_project/build
conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -b=outdated -u conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -b=outdated -u
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
cmake --build . cmake --build .
Install
^^^^^^^
In case you don't want to use Conan in your project and just want to install the **mp-units**
library on your file system and use it via ``find_package(mp-units)`` from another repository
to find it, it is enough to perform the following steps:
.. code-block:: shell
mkdir units/build && cd units/build
conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -b=missing
cmake ../src -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
cmake --install . --prefix <install_dir>
Contributing (or just building all the tests, examples, and documentation) Contributing (or just building all the tests, examples, and documentation)
-------------------------------------------------------------------------- --------------------------------------------------------------------------
@@ -349,10 +363,10 @@ in **mp-units** repository, you should:
.. code-block:: shell .. code-block:: shell
conan remote add linear-algebra https://api.bintray.com/conan/twonington/public-conan conan remote add linear-algebra https://twonington.jfrog.io/artifactory/api/conan/conan-oss
git clone https://github.com/mpusz/units.git && cd units git clone https://github.com/mpusz/units.git && cd units
pip3 install -r docs/requirements.txt pip3 install -r docs/requirements.txt
mkdir build && cd build mkdir units/build && cd units/build
conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -e mp-units:CONAN_RUN_TESTS=True -b outdated -u conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -e mp-units:CONAN_RUN_TESTS=True -b outdated -u
conan build .. conan build ..
@@ -387,4 +401,4 @@ Uploading **mp-units** Package to the Conan Server
.. code-block:: shell .. code-block:: shell
conan upload -r <remote-name> --all mp-units/0.7.0@<user>/<channel> conan upload -r <remote-name> --all mp-units/0.8.0@<user>/<channel>

View File

@@ -118,7 +118,7 @@ coherent unit::
exponent<si::dim_area, 1>, exponent<si::dim_time, -1>> {}; exponent<si::dim_area, 1>, exponent<si::dim_time, -1>> {};
// our unit of interest for a new derived dimension // our unit of interest for a new derived dimension
struct desk_per_hour : deduced_unit<desk_per_hour, dim_desk_rate, desk, si::hour> {}; struct desk_per_hour : derived_unit<desk_per_hour, dim_desk_rate, desk, si::hour> {};
// a quantity of our dimension // a quantity of our dimension
template<UnitOf<dim_desk_rate> U, Representation Rep = double> template<UnitOf<dim_desk_rate> U, Representation Rep = double>
@@ -167,7 +167,7 @@ With the above we can now define a new derived dimension::
exponent<dim_people, 1>, exponent<dim_people, 1>,
exponent<si::dim_area, -1>> {}; exponent<si::dim_area, -1>> {};
struct person_per_desk : deduced_unit<person_per_desk, dim_occupancy_rate, person, desk> {}; struct person_per_desk : derived_unit<person_per_desk, dim_occupancy_rate, person, desk> {};
template<UnitOf<dim_occupancy_rate> U, Representation Rep = double> template<UnitOf<dim_occupancy_rate> U, Representation Rep = double>
using occupancy_rate = quantity<dim_occupancy_rate, U, Rep>; using occupancy_rate = quantity<dim_occupancy_rate, U, Rep>;

View File

@@ -56,11 +56,12 @@ such an explicit conversion::
For external quantity point-like types, `quantity_point_like_traits` is also provided. For external quantity point-like types, `quantity_point_like_traits` is also provided.
It works just like `quantity_like_traits`, except that It works just like `quantity_like_traits`, except that
``number(T)`` is replaced with ``relative(T)`` that returns the `QuantityLike` value. ``number(T)`` is replaced with ``relative(T)`` that returns the `QuantityLike` value
and ``dimension`` is replaced with ``origin``.
Similar to `quantity` and `quantity_kind`, `quantity_point` and `quantity_kind_point` Similar to `quantity` and `quantity_kind`, `quantity_point` and `quantity_kind_point`
provide a deduction guide from `QuantityPointLike`:: provide a deduction guide from `QuantityPointLike`::
using namespace std::chrono_literals; using namespace std::chrono_literals;
static_assert(quantity_point{std::chrono::sys_seconds{1s}} + 1 * s == quantity_point{2s}); static_assert((quantity_point{std::chrono::sys_seconds{1s}} + 1 * s).relative() == 2s);

View File

@@ -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 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 <https://wg21.link/P1385>`_ Linear Algebra Library for the C++23 defined in `P1385 <https://wg21.link/P1385>`_
and its latest implementation from `GitHub <https://github.com/BobSteagall/wg21>`_ and its latest implementation from `GitHub <https://github.com/BobSteagall/wg21>`_
or `Conan <https://bintray.com/twonington/public-conan/linear_algebra%3Apublic-conan>`_. or `Conan <https://twonington.jfrog.io/artifactory/api/conan/conan-oss>`_.
Also, to simplify the examples all of them assume:: Also, to simplify the examples all of them assume::
using namespace std::math; using namespace std::math;

View File

@@ -28,7 +28,10 @@ cmake_minimum_required(VERSION 3.2)
function(add_example target) function(add_example target)
add_executable(${target}-aliases ${target}.cpp) add_executable(${target}-aliases ${target}.cpp)
target_link_libraries(${target}-aliases PRIVATE ${ARGN}) target_link_libraries(${target}-aliases PRIVATE ${ARGN})
target_compile_definitions(${target}-aliases PRIVATE UNITS_ALIASES) target_compile_definitions(${target}-aliases PRIVATE
UNITS_NO_LITERALS
UNITS_NO_REFERENCES
)
endfunction() endfunction()
add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international) add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international)
@@ -43,7 +46,10 @@ add_example(unknown_dimension mp-units::core-io mp-units::si)
if(NOT UNITS_LIBCXX) if(NOT UNITS_LIBCXX)
add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer) add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer)
target_compile_definitions(glide_computer_example-aliases PRIVATE UNITS_REFERENCES) target_compile_definitions(glide_computer_example-aliases PRIVATE
UNITS_NO_LITERALS
UNITS_NO_REFERENCES
)
find_package(linear_algebra CONFIG REQUIRED) find_package(linear_algebra CONFIG REQUIRED)
add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si) add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si)

View File

@@ -53,8 +53,8 @@ distance spherical_distance(position from, position to)
return distance(earth_radius * central_angle); return distance(earth_radius * central_angle);
} else { } else {
// the haversine formula // the haversine formula
const auto sin_lat = sin(lat2 - lat1) / 2; const auto sin_lat = sin((lat2 - lat1) / 2);
const auto sin_lon = sin(lon2 - lon1) / 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)); 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); return distance(earth_radius * central_angle);
} }

View File

@@ -30,6 +30,7 @@
#include <units/quantity_point_kind.h> #include <units/quantity_point_kind.h>
// IWYU pragma: end_exports // IWYU pragma: end_exports
#include <units/chrono.h>
#include <units/format.h> #include <units/format.h>
#include <units/math.h> // IWYU pragma: keep #include <units/math.h> // IWYU pragma: keep
#include <algorithm> #include <algorithm>
@@ -77,8 +78,8 @@ constexpr units::Dimensionless auto operator/(const QK1& lhs, const QK2& rhs)
using horizontal_kind = geographic::horizontal_kind; using horizontal_kind = geographic::horizontal_kind;
struct vertical_kind : units::kind<vertical_kind, units::isq::si::dim_length> {}; struct vertical_kind : units::kind<vertical_kind, units::isq::si::dim_length> {};
struct vertical_point_kind : units::point_kind<vertical_point_kind, vertical_kind> {}; struct vertical_point_kind : units::point_kind<vertical_point_kind, vertical_kind> {};
struct velocity_kind : units::derived_kind<velocity_kind, horizontal_kind, units::isq::si::dim_speed> {}; struct velocity_kind : units::derived_kind<velocity_kind, units::isq::si::dim_speed, horizontal_kind> {};
struct rate_of_climb_kind : units::derived_kind<rate_of_climb_kind, vertical_kind, units::isq::si::dim_speed> {}; struct rate_of_climb_kind : units::derived_kind<rate_of_climb_kind, units::isq::si::dim_speed, vertical_kind> {};
// https://en.wikipedia.org/wiki/Flight_planning#Units_of_measurement // https://en.wikipedia.org/wiki/Flight_planning#Units_of_measurement
// length // length
@@ -88,7 +89,7 @@ using altitude = units::quantity_point_kind<vertical_point_kind, units::isq::si:
// time // time
using duration = units::isq::si::time<units::isq::si::second>; using duration = units::isq::si::time<units::isq::si::second>;
using timestamp = units::quantity_point<units::isq::si::dim_time, units::isq::si::second>; using timestamp = units::quantity_point<units::clock_origin<std::chrono::system_clock>, units::isq::si::second>;
// speed // speed
using velocity = units::quantity_kind<velocity_kind, units::isq::si::kilometre_per_hour>; using velocity = units::quantity_kind<velocity_kind, units::isq::si::kilometre_per_hour>;

View File

@@ -20,10 +20,6 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
#define UNITS_ALIASES
#define UNITS_LITERALS
#define UNITS_REFERENCES
#include <units/format.h> #include <units/format.h>
#include <units/isq/si/international/length.h> #include <units/isq/si/international/length.h>
#include <units/isq/si/international/speed.h> // IWYU pragma: keep #include <units/isq/si/international/speed.h> // IWYU pragma: keep

View File

@@ -28,7 +28,10 @@ cmake_minimum_required(VERSION 3.2)
function(add_example target) function(add_example target)
add_executable(${target} ${target}.cpp) add_executable(${target} ${target}.cpp)
target_link_libraries(${target} PRIVATE ${ARGN}) target_link_libraries(${target} PRIVATE ${ARGN})
target_compile_definitions(${target} PRIVATE UNITS_REFERENCES) target_compile_definitions(${target} PRIVATE
UNITS_NO_LITERALS
UNITS_NO_ALIASES
)
endfunction() endfunction()
add_example(kalman_filter-example_1 mp-units::core-fmt mp-units::si) add_example(kalman_filter-example_1 mp-units::core-fmt mp-units::si)

View File

@@ -28,7 +28,10 @@ cmake_minimum_required(VERSION 3.2)
function(add_example target) function(add_example target)
add_executable(${target}-literals ${target}.cpp) add_executable(${target}-literals ${target}.cpp)
target_link_libraries(${target}-literals PRIVATE ${ARGN}) target_link_libraries(${target}-literals PRIVATE ${ARGN})
target_compile_definitions(${target}-literals PRIVATE UNITS_LITERALS) target_compile_definitions(${target}-literals PRIVATE
UNITS_NO_REFERENCES
UNITS_NO_ALIASES
)
endfunction() endfunction()
add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international) add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international)
@@ -42,7 +45,10 @@ add_example(unknown_dimension mp-units::core-io mp-units::si)
if(NOT UNITS_LIBCXX) if(NOT UNITS_LIBCXX)
add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer) add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer)
target_compile_definitions(glide_computer_example-literals PRIVATE UNITS_LITERALS) target_compile_definitions(glide_computer_example-literals PRIVATE
UNITS_NO_REFERENCES
UNITS_NO_ALIASES
)
find_package(linear_algebra CONFIG REQUIRED) find_package(linear_algebra CONFIG REQUIRED)
add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si) add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si)

View File

@@ -28,7 +28,10 @@ cmake_minimum_required(VERSION 3.2)
function(add_example target) function(add_example target)
add_executable(${target}-references ${target}.cpp) add_executable(${target}-references ${target}.cpp)
target_link_libraries(${target}-references PRIVATE ${ARGN}) target_link_libraries(${target}-references PRIVATE ${ARGN})
target_compile_definitions(${target}-references PRIVATE UNITS_REFERENCES) target_compile_definitions(${target}-references PRIVATE
UNITS_NO_LITERALS
UNITS_NO_ALIASES
)
endfunction() endfunction()
add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international) add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international)
@@ -42,7 +45,10 @@ add_example(unknown_dimension mp-units::core-io mp-units::si)
if(NOT UNITS_LIBCXX) if(NOT UNITS_LIBCXX)
add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer) add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer)
target_compile_definitions(glide_computer_example-references PRIVATE UNITS_REFERENCES) target_compile_definitions(glide_computer_example-references PRIVATE
UNITS_NO_LITERALS
UNITS_NO_ALIASES
)
find_package(linear_algebra CONFIG REQUIRED) find_package(linear_algebra CONFIG REQUIRED)
add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si) add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si)

View File

@@ -22,7 +22,7 @@
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.15)
project(mp-units project(mp-units
VERSION 0.7.0 VERSION 0.8.0
LANGUAGES CXX LANGUAGES CXX
) )

View File

@@ -205,6 +205,52 @@ concept UnitOf =
Dimension<D> && Dimension<D> &&
std::same_as<typename U::reference, typename dimension_unit<D>::reference>; std::same_as<typename U::reference, typename dimension_unit<D>::reference>;
// PointOrigin
template<Dimension D>
struct point_origin;
/**
* @brief A concept matching a point origin
*
* Satisfied by types derived from an specialization of @c point_origin.
*/
template<typename T>
concept PointOrigin = is_derived_from_specialization_of<T, point_origin> &&
requires {
typename T::dimension;
requires Dimension<typename T::dimension>;
typename T::point_origin;
requires std::same_as<typename T::point_origin, point_origin<typename T::dimension>>;
requires !std::same_as<T, point_origin<typename T::dimension>>;
};
// RebindablePointOriginFor
namespace detail {
template<typename O, typename D>
struct rebind_point_origin_dimension_impl {
using type = typename O::template rebind<D>;
};
} // namespace detail
template<PointOrigin O, Dimension D>
using rebind_point_origin_dimension = typename conditional<is_same_v<typename O::dimension, D>, std::type_identity<O>,
detail::rebind_point_origin_dimension_impl<O, D>>::type;
/**
* @brief A concept predicating the possibility of changing an origin's dimension
*
* Satisfied by point origins whose dimension can be made to be `D`.
*/
template<typename T, typename D>
concept RebindablePointOriginFor =
requires { typename rebind_point_origin_dimension<T, D>; } &&
PointOrigin<rebind_point_origin_dimension<T, D>> &&
std::same_as<D, typename rebind_point_origin_dimension<T, D>::dimension>;
// Kind // Kind
namespace detail { namespace detail {
@@ -216,7 +262,7 @@ struct _kind_base;
template<typename T, template<typename...> typename Base> template<typename T, template<typename...> typename Base>
concept kind_impl_ = concept kind_impl_ =
is_derived_from_specialization_of<T, Base> && is_derived_from_specialization_of<T, Base> &&
requires(T* t) { requires {
typename T::base_kind; typename T::base_kind;
typename T::dimension; typename T::dimension;
requires Dimension<typename T::dimension>; requires Dimension<typename T::dimension>;
@@ -236,7 +282,7 @@ concept Kind =
// PointKind // PointKind
namespace detail { namespace detail {
template<Kind> template<Kind, PointOrigin>
struct _point_kind_base; struct _point_kind_base;
} // namespace detail } // namespace detail
@@ -247,7 +293,12 @@ struct _point_kind_base;
* Satisfied by all point kind types derived from an specialization of @c point_kind. * Satisfied by all point kind types derived from an specialization of @c point_kind.
*/ */
template<typename T> template<typename T>
concept PointKind = kind_impl_<T, detail::_point_kind_base>; concept PointKind =
kind_impl_<T, detail::_point_kind_base> &&
requires { typename T::origin; } &&
PointOrigin<typename T::origin> &&
std::same_as<typename T::dimension, typename T::base_kind::dimension> &&
std::same_as<typename T::dimension, typename T::origin::dimension>;
// Reference // Reference
namespace detail { namespace detail {

View File

@@ -31,7 +31,7 @@ namespace units {
template<Dimension D, UnitOf<D> U, Representation Rep> template<Dimension D, UnitOf<D> U, Representation Rep>
class quantity; class quantity;
template<Dimension D, UnitOf<D> U, Representation Rep> template<PointOrigin O, UnitOf<typename O::dimension> U, Representation Rep>
class quantity_point; class quantity_point;
template<Kind K, UnitOf<typename K::dimension> U, Representation Rep> template<Kind K, UnitOf<typename K::dimension> U, Representation Rep>
@@ -99,7 +99,8 @@ template<units::QuantityPoint QP1, units::QuantityPointEquivalentTo<QP1> QP2>
requires requires { typename common_type_t<typename QP1::rep, typename QP2::rep>; } requires requires { typename common_type_t<typename QP1::rep, typename QP2::rep>; }
struct common_type<QP1, QP2> { struct common_type<QP1, QP2> {
using type = units::quantity_point< using type = units::quantity_point<
typename common_type_t<typename QP1::quantity_type, typename QP2::quantity_type>::dimension, units::rebind_point_origin_dimension<typename QP1::origin,
typename common_type_t<typename QP1::quantity_type, typename QP2::quantity_type>::dimension>,
typename common_type_t<typename QP1::quantity_type, typename QP2::quantity_type>::unit, typename common_type_t<typename QP1::quantity_type, typename QP2::quantity_type>::unit,
typename common_type_t<typename QP1::quantity_type, typename QP2::quantity_type>::rep>; typename common_type_t<typename QP1::quantity_type, typename QP2::quantity_type>::rep>;
}; };

View File

@@ -80,16 +80,16 @@ template<typename... Es>
inline constexpr int negative_exp_count = ((Es::num < 0 ? 1 : 0) + ... + 0); inline constexpr int negative_exp_count = ((Es::num < 0 ? 1 : 0) + ... + 0);
template<typename... Us, typename... Es, std::size_t... Idxs> template<typename... Us, typename... Es, std::size_t... Idxs>
constexpr auto deduced_symbol_text(exponent_list<Es...>, std::index_sequence<Idxs...>) constexpr auto derived_symbol_text(exponent_list<Es...>, std::index_sequence<Idxs...>)
{ {
constexpr auto neg_exp = negative_exp_count<Es...>; constexpr auto neg_exp = negative_exp_count<Es...>;
return (exp_text<Es, Us::symbol, neg_exp, Idxs>() + ...); return (exp_text<Es, Us::symbol, neg_exp, Idxs>() + ...);
} }
template<DerivedDimension Dim, Unit... Us> template<DerivedDimension Dim, Unit... Us>
constexpr auto deduced_symbol_text() constexpr auto derived_symbol_text()
{ {
return deduced_symbol_text<Us...>(typename Dim::recipe(), std::index_sequence_for<Us...>()); return derived_symbol_text<Us...>(typename Dim::recipe(), std::index_sequence_for<Us...>());
} }
} // namespace units::detail } // namespace units::detail

View File

@@ -33,7 +33,7 @@ inline constexpr bool same_scaled_units = false;
template<typename... Es, Unit... Us> template<typename... Es, Unit... Us>
inline constexpr bool same_scaled_units<exponent_list<Es...>, Us...> = (UnitOf<Us, typename Es::dimension> && ...); inline constexpr bool same_scaled_units<exponent_list<Es...>, Us...> = (UnitOf<Us, typename Es::dimension> && ...);
// deduced_unit // derived_unit
template<Exponent E> template<Exponent E>
constexpr ratio inverse_if_negative(const ratio& r) constexpr ratio inverse_if_negative(const ratio& r)
@@ -51,6 +51,6 @@ constexpr ratio derived_ratio(exponent_list<Es...>)
} }
template<DerivedDimension D, Unit... Us> template<DerivedDimension D, Unit... Us>
using deduced_unit = scaled_unit<derived_ratio<Us...>(typename D::recipe()), typename D::coherent_unit::reference>; using derived_unit = scaled_unit<derived_ratio<Us...>(typename D::recipe()), typename D::coherent_unit::reference>;
} // namespace units::detail } // namespace units::detail

View File

@@ -81,29 +81,51 @@ template<Unit U1, Dimension D1, Unit U2, Dimension D2>
struct equivalent_unit : std::disjunction<equivalent_impl<U1, U2>, struct equivalent_unit : std::disjunction<equivalent_impl<U1, U2>,
std::bool_constant<U1::ratio / dimension_unit<D1>::ratio == U2::ratio / dimension_unit<D2>::ratio>> {}; std::bool_constant<U1::ratio / dimension_unit<D1>::ratio == U2::ratio / dimension_unit<D2>::ratio>> {};
// point origins
template<typename T, typename U>
concept EquivalentPointOrigins =
RebindablePointOriginFor<T, typename U::dimension> && RebindablePointOriginFor<U, typename T::dimension> &&
std::same_as<T, rebind_point_origin_dimension<U, typename T::dimension>> &&
std::same_as<U, rebind_point_origin_dimension<T, typename U::dimension>>;
template<PointOrigin T, PointOrigin U>
struct equivalent_impl<T, U> : std::bool_constant<
EquivalentPointOrigins<T, U> && equivalent_impl<typename T::dimension, typename U::dimension>::value> {};
// (point) kinds // (point) kinds
template<typename T, typename U> template<Kind T, Kind U>
requires (Kind<T> && Kind<U>) || (PointKind<T> && PointKind<U>)
struct equivalent_impl<T, U> : struct equivalent_impl<T, U> :
std::conjunction<std::is_same<typename T::base_kind, typename U::base_kind>, std::conjunction<std::is_same<typename T::base_kind, typename U::base_kind>,
equivalent_impl<typename T::dimension, typename U::dimension>> {}; equivalent_impl<typename T::dimension, typename U::dimension>> {};
template<PointKind T, PointKind U>
struct equivalent_impl<T, U> :
std::conjunction<equivalent_impl<typename T::base_kind, typename U::base_kind>,
equivalent_impl<typename T::origin, typename U::origin>> {};
// quantities, quantity points, quantity (point) kinds // quantities, quantity points, quantity (point) kinds
template<typename Q1, typename Q2> template<Quantity Q1, Quantity Q2>
requires (Quantity<Q1> && Quantity<Q2>) || (QuantityPoint<Q1> && QuantityPoint<Q2>)
struct equivalent_impl<Q1, Q2> : std::conjunction<equivalent_impl<typename Q1::dimension, typename Q2::dimension>, struct equivalent_impl<Q1, Q2> : std::conjunction<equivalent_impl<typename Q1::dimension, typename Q2::dimension>,
equivalent_unit<typename Q1::unit, typename Q1::dimension, equivalent_unit<typename Q1::unit, typename Q1::dimension,
typename Q2::unit, typename Q2::dimension>> {}; typename Q2::unit, typename Q2::dimension>> {};
template<typename QK1, typename QK2> template<QuantityPoint QP1, QuantityPoint QP2>
requires (QuantityKind<QK1> && QuantityKind<QK2>) || (QuantityPointKind<QK1> && QuantityPointKind<QK2>) struct equivalent_impl<QP1, QP2> : std::conjunction<equivalent_impl<typename QP1::quantity_type, typename QP2::quantity_type>,
equivalent_impl<typename QP1::origin, typename QP2::origin>> {};
template<QuantityKind QK1, QuantityKind QK2>
struct equivalent_impl<QK1, QK2> : std::conjunction<equivalent_impl<typename QK1::kind_type, typename QK2::kind_type>, struct equivalent_impl<QK1, QK2> : std::conjunction<equivalent_impl<typename QK1::kind_type, typename QK2::kind_type>,
equivalent_impl<typename QK1::quantity_type, typename QK2::quantity_type>> {}; equivalent_impl<typename QK1::quantity_type, typename QK2::quantity_type>> {};
template<QuantityPointKind QPK1, QuantityPointKind QPK2>
struct equivalent_impl<QPK1, QPK2> : std::conjunction<equivalent_impl<typename QPK1::quantity_kind_type, typename QPK2::quantity_kind_type>,
equivalent_impl<typename QPK1::origin, typename QPK2::origin>> {};
} // namespace detail } // namespace detail
template<typename T, typename U> template<typename T, typename U>

View File

@@ -85,21 +85,20 @@ template<typename Q1, typename Q2>
concept QuantityEquivalentTo = Quantity<Q1> && QuantityOf<Q2, typename Q1::dimension>; concept QuantityEquivalentTo = Quantity<Q1> && QuantityOf<Q2, typename Q1::dimension>;
/** /**
* @brief A concept matching all quantity points with provided dimension * @brief A concept matching all quantity points of the provided origin
* *
* Satisfied by all quantity points with a dimension being the instantiation derived from * Satisfied by all quantity points with an origin equivalent to the provided one.
* the provided dimension type.
*/ */
template<typename QP, typename Dim> template<typename QP, typename Orig>
concept QuantityPointOf = QuantityPoint<QP> && Dimension<Dim> && equivalent<typename QP::dimension, Dim>; concept QuantityPointOf = QuantityPoint<QP> && PointOrigin<Orig> && equivalent<typename QP::origin, Orig>;
/** /**
* @brief A concept matching two equivalent quantity points * @brief A concept matching two equivalent quantity points
* *
* Satisfied by quantity points having equivalent dimensions. * Satisfied by quantity points having equivalent origins.
*/ */
template<typename QP1, typename QP2> template<typename QP1, typename QP2>
concept QuantityPointEquivalentTo = QuantityPoint<QP1> && QuantityPointOf<QP2, typename QP1::dimension>; concept QuantityPointEquivalentTo = QuantityPoint<QP1> && QuantityPointOf<QP2, typename QP1::origin>;
/** /**
* @brief A concept matching only quantity kinds of a specific kind. * @brief A concept matching only quantity kinds of a specific kind.

View File

@@ -22,7 +22,7 @@
#pragma once #pragma once
#include <units/bits/deduced_symbol_text.h> #include <units/bits/derived_symbol_text.h>
#include <units/bits/external/text_tools.h> #include <units/bits/external/text_tools.h>
#include <units/prefix.h> #include <units/prefix.h>
#include <units/derived_dimension.h> #include <units/derived_dimension.h>

View File

@@ -25,6 +25,7 @@
#include <units/customization_points.h> #include <units/customization_points.h>
// IWYU pragma: begin_exports // IWYU pragma: begin_exports
#include <units/isq/si/time.h> #include <units/isq/si/time.h>
#include <units/point_origin.h>
#include <chrono> #include <chrono>
// IWYU pragma: end_exports // IWYU pragma: end_exports
@@ -38,10 +39,13 @@ struct quantity_like_traits<std::chrono::duration<Rep, Period>> {
[[nodiscard]] static constexpr rep number(const std::chrono::duration<Rep, Period>& q) { return q.count(); } [[nodiscard]] static constexpr rep number(const std::chrono::duration<Rep, Period>& q) { return q.count(); }
}; };
template<typename C>
struct clock_origin : point_origin<isq::si::dim_time> { };
template<typename C, typename Rep, typename Period> template<typename C, typename Rep, typename Period>
struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::duration<Rep, Period>>> { struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::duration<Rep, Period>>> {
using dimension = isq::si::dim_time; using origin = clock_origin<C>;
using unit = downcast_unit<dimension, ratio(Period::num, Period::den)>; using unit = downcast_unit<typename origin::dimension, ratio(Period::num, Period::den)>;
using rep = Rep; using rep = Rep;
[[nodiscard]] static constexpr auto relative( [[nodiscard]] static constexpr auto relative(
const std::chrono::time_point<C, std::chrono::duration<Rep, Period>>& qp) { const std::chrono::time_point<C, std::chrono::duration<Rep, Period>>& qp) {
@@ -49,4 +53,11 @@ struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::durati
} }
}; };
namespace detail {
template<typename C, typename Rep, typename Period>
inline constexpr bool is_quantity_point_like<std::chrono::time_point<C, std::chrono::duration<Rep, Period>>> = true;
} // namespace detail
} // namespace units } // namespace units

View File

@@ -88,7 +88,7 @@ struct quantity_like_traits;
/** /**
* @brief Provides support for external quantity point-like types * @brief Provides support for external quantity point-like types
* *
* The type trait should provide the following nested type aliases: @c dimension, @c unit, @c rep, * The type trait should provide the following nested type aliases: @c origin, @c unit, @c rep,
* and a static member function @c relative(T) that will return the quantity-like value of the quantity point. * and a static member function @c relative(T) that will return the quantity-like value of the quantity point.
* *
* Usage example can be found in @c units/chrono.h header file. * Usage example can be found in @c units/chrono.h header file.

View File

@@ -43,7 +43,7 @@ concept Angle = QuantityOfT<T, dim_angle>;
template<UnitOf<dim_angle<>> U, Representation Rep = double> template<UnitOf<dim_angle<>> U, Representation Rep = double>
using angle = quantity<dim_angle<>, U, Rep>; using angle = quantity<dim_angle<>, U, Rep>;
#ifdef UNITS_LITERALS #ifndef UNITS_NO_LITERALS
inline namespace literals { inline namespace literals {
@@ -53,9 +53,9 @@ constexpr auto operator"" _q_rad(long double l) { return angle<radian, long doub
} // namespace literals } // namespace literals
#endif // UNITS_LITERALS #endif // UNITS_NO_LITERALS
#ifdef UNITS_REFERENCES #ifndef UNITS_NO_REFERENCES
namespace angle_references { namespace angle_references {
@@ -69,6 +69,6 @@ using namespace angle_references;
} // namespace references } // namespace references
#endif // UNITS_REFERENCES #endif // UNITS_NO_REFERENCES
} // namespace units } // namespace units

View File

@@ -27,6 +27,9 @@
namespace units { namespace units {
template<Dimension D>
struct dynamic_origin;
namespace detail { namespace detail {
template<typename K, Dimension D> template<typename K, Dimension D>
@@ -35,10 +38,11 @@ struct _kind_base : downcast_base<_kind_base<K, D>> {
using dimension = D; using dimension = D;
}; };
template<Kind K> template<Kind K, PointOrigin O>
struct _point_kind_base : downcast_base<_point_kind_base<K>> { struct _point_kind_base : downcast_base<_point_kind_base<K, O>> {
using base_kind = K; using base_kind = K;
using dimension = typename K::dimension; using dimension = typename K::dimension;
using origin = O;
}; };
} // namespace detail } // namespace detail
@@ -47,18 +51,18 @@ template<Kind K, Dimension D>
requires Kind<downcast<detail::_kind_base<typename K::base_kind, D>>> requires Kind<downcast<detail::_kind_base<typename K::base_kind, D>>>
using downcast_kind = downcast<detail::_kind_base<typename K::base_kind, D>>; using downcast_kind = downcast<detail::_kind_base<typename K::base_kind, D>>;
template<Kind K> template<Kind K, PointOrigin O = dynamic_origin<typename K::dimension>>
requires PointKind<downcast<detail::_point_kind_base<K>>> requires PointKind<downcast<detail::_point_kind_base<K, O>>>
using downcast_point_kind = downcast<detail::_point_kind_base<K>>; using downcast_point_kind = downcast<detail::_point_kind_base<K, O>>;
template<typename K, Dimension D> template<typename K, Dimension D>
struct kind : downcast_dispatch<K, detail::_kind_base<K, D>> {}; struct kind : downcast_dispatch<K, detail::_kind_base<K, D>> {};
template<typename DK, Kind BK, Dimension D> template<typename DK, Dimension D, Kind BK>
requires std::same_as<BK, typename BK::base_kind> requires std::same_as<BK, typename BK::base_kind>
struct derived_kind : downcast_dispatch<DK, detail::_kind_base<BK, D>> {}; struct derived_kind : downcast_dispatch<DK, detail::_kind_base<BK, D>> {};
template<typename DPK, Kind BK> template<typename DPK, Kind BK, PointOrigin O = dynamic_origin<typename BK::dimension>>
struct point_kind : downcast_dispatch<DPK, detail::_point_kind_base<BK>> {}; struct point_kind : downcast_dispatch<DPK, detail::_point_kind_base<BK, O>> {};
} // namespace units } // namespace units

View File

@@ -0,0 +1,34 @@
// 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 <units/bits/basic_concepts.h>
namespace units {
template<Dimension D>
struct point_origin {
using dimension = D;
};
} // namespace units

View File

@@ -147,9 +147,10 @@ public:
quantity(const quantity&) = default; quantity(const quantity&) = default;
quantity(quantity&&) = default; quantity(quantity&&) = default;
template<safe_convertible_to_<rep> Value> template<typename Value>
constexpr explicit(!(is_same_v<dimension, dim_one> && is_same_v<unit, ::units::one>)) requires safe_convertible_to_<std::remove_cvref_t<Value>, rep>
quantity(const Value& v) : number_(v) {} constexpr explicit(!(std::same_as<dimension, dim_one> && std::same_as<unit, ::units::one>))
quantity(Value&& v) : number_(std::forward<Value>(v)) {}
template<safe_castable_to_<quantity> Q> template<safe_castable_to_<quantity> Q>
constexpr explicit(false) quantity(const Q& q) : number_(quantity_cast<quantity>(q).number()) {} constexpr explicit(false) quantity(const Q& q) : number_(quantity_cast<quantity>(q).number()) {}
@@ -162,7 +163,10 @@ public:
quantity& operator=(quantity&&) = default; quantity& operator=(quantity&&) = default;
// data access // data access
[[nodiscard]] constexpr rep number() const noexcept { return number_; } [[nodiscard]] constexpr rep& number() & noexcept { return number_; }
[[nodiscard]] constexpr const rep& number() const & noexcept { return number_; }
[[nodiscard]] constexpr rep&& number() && noexcept { return std::move(number_); }
[[nodiscard]] constexpr const rep&& number() const && noexcept { return std::move(number_); }
// member unary operators // member unary operators
[[nodiscard]] constexpr Quantity auto operator+() const [[nodiscard]] constexpr Quantity auto operator+() const
@@ -363,11 +367,12 @@ public:
} }
[[nodiscard]] friend constexpr Quantity auto operator%(const quantity& lhs, const quantity& rhs) [[nodiscard]] friend constexpr Quantity auto operator%(const quantity& lhs, const quantity& rhs)
requires (!floating_point_<rep>) && is_same_v<unit, units::one> && requires (!floating_point_<rep>) &&
invoke_result_convertible_to_<rep, std::modulus<>, rep, rep> invoke_result_convertible_to_<rep, std::modulus<>, rep, rep>
{ {
gsl_ExpectsAudit(rhs.number() != quantity_values<rep>::zero()); gsl_ExpectsAudit(rhs.number() != quantity_values<rep>::zero());
return units::quantity(lhs.number() % rhs.number()); using ret = quantity<D, U, std::invoke_result_t<std::modulus<>, rep, rep>>;
return ret(lhs.number() % rhs.number());
} }
[[nodiscard]] friend constexpr auto operator<=>(const quantity& lhs, const quantity& rhs) [[nodiscard]] friend constexpr auto operator<=>(const quantity& lhs, const quantity& rhs)
@@ -422,25 +427,15 @@ template<Quantity Q1, Quantity Q2>
return detail::make_quantity<Q1::reference / Q2::reference>(lhs.number() / rhs.number()); return detail::make_quantity<Q1::reference / Q2::reference>(lhs.number() / rhs.number());
} }
template<typename D1, typename U1, typename Rep1, typename U2, typename Rep2> template<Quantity Q1, Quantity Q2>
requires (!floating_point_<Rep1>) && (!floating_point_<Rep2>) &&
quantity_value_for_<std::modulus<>, Rep1, Rep2>
[[nodiscard]] constexpr Quantity auto operator%(const quantity<D1, U1, Rep1>& lhs, const quantity<dim_one, U2, Rep2>& rhs)
{
gsl_ExpectsAudit(rhs.number() != quantity_values<Rep2>::zero());
using unit = downcast_unit<D1, U1::ratio * U2::ratio>;
using ret = quantity<D1, unit, std::invoke_result_t<std::modulus<>, Rep1, Rep2>>;
return ret(lhs.number() % rhs.number());
}
template<Quantity Q1, QuantityEquivalentTo<Q1> Q2>
requires (!floating_point_<typename Q1::rep>) && (!floating_point_<typename Q2::rep>) && requires (!floating_point_<typename Q1::rep>) && (!floating_point_<typename Q2::rep>) &&
(QuantityEquivalentTo<Q2, Q1> || Dimensionless<Q2>) &&
quantity_value_for_<std::modulus<>, typename Q1::rep, typename Q2::rep> quantity_value_for_<std::modulus<>, typename Q1::rep, typename Q2::rep>
[[nodiscard]] constexpr Quantity auto operator%(const Q1& lhs, const Q2& rhs) [[nodiscard]] constexpr Quantity auto operator%(const Q1& lhs, const Q2& rhs)
{ {
gsl_ExpectsAudit(rhs.number() != quantity_values<typename Q2::rep>::zero()); gsl_ExpectsAudit(rhs.number() != quantity_values<typename Q2::rep>::zero());
using ret = common_quantity_for<std::modulus<>, Q1, Q2>; using ret = quantity<typename Q1::dimension, typename Q1::unit, std::invoke_result_t<std::modulus<>, typename Q1::rep, typename Q2::rep>>;
return ret(ret(lhs).number() % ret(rhs).number()); return ret(lhs.number() % rhs.number());
} }
template<Quantity Q1, QuantityEquivalentTo<Q1> Q2> template<Quantity Q1, QuantityEquivalentTo<Q1> Q2>

View File

@@ -39,7 +39,7 @@ namespace units {
template<Dimension D, UnitOf<D> U, Representation Rep> template<Dimension D, UnitOf<D> U, Representation Rep>
class quantity; class quantity;
template<Dimension D, UnitOf<D> U, Representation Rep> template<PointOrigin O, UnitOf<typename O::dimension> U, Representation Rep>
class quantity_point; class quantity_point;
template<Kind K, UnitOf<typename K::dimension> U, Representation Rep> template<Kind K, UnitOf<typename K::dimension> U, Representation Rep>
@@ -234,10 +234,12 @@ template<Representation ToRep, typename D, typename U, scalable_with_<ToRep> Rep
* *
* @tparam CastSpec a target quantity point type to cast to or anything that works for quantity_cast * @tparam CastSpec a target quantity point type to cast to or anything that works for quantity_cast
*/ */
template<typename CastSpec, typename D, typename U, typename Rep> template<typename CastSpec, typename O, typename U, typename Rep>
requires is_specialization_of<CastSpec, quantity_point> || [[nodiscard]] constexpr auto quantity_point_cast(const quantity_point<O, U, Rep>& qp)
requires(quantity<D, U, Rep> q) { quantity_cast<CastSpec>(q); } requires requires { requires is_specialization_of<CastSpec, quantity_point>;
[[nodiscard]] constexpr auto quantity_point_cast(const quantity_point<D, U, Rep>& qp) requires requires { quantity_cast<typename CastSpec::quantity_type>(qp.relative()); };
requires equivalent<O, typename CastSpec::origin>; } || // TODO: Simplify when Clang catches up.
requires { quantity_cast<CastSpec>(qp.relative()); }
{ {
if constexpr (is_specialization_of<CastSpec, quantity_point>) if constexpr (is_specialization_of<CastSpec, quantity_point>)
return quantity_point(quantity_cast<typename CastSpec::quantity_type>(qp.relative())); return quantity_point(quantity_cast<typename CastSpec::quantity_type>(qp.relative()));
@@ -261,11 +263,11 @@ template<typename CastSpec, typename D, typename U, typename Rep>
* @tparam ToD a dimension type to use for a target quantity * @tparam ToD a dimension type to use for a target quantity
* @tparam ToU a unit type to use for a target quantity * @tparam ToU a unit type to use for a target quantity
*/ */
template<Dimension ToD, Unit ToU, typename D, typename U, typename Rep> template<Dimension ToD, Unit ToU, typename O, typename U, typename Rep>
requires equivalent<ToD, D> && UnitOf<ToU, ToD> requires equivalent<ToD, typename O::dimension> && UnitOf<ToU, ToD> && RebindablePointOriginFor<O, ToD>
[[nodiscard]] constexpr auto quantity_point_cast(const quantity_point<D, U, Rep>& q) [[nodiscard]] constexpr auto quantity_point_cast(const quantity_point<O, U, Rep>& q)
{ {
return quantity_point_cast<quantity_point<ToD, ToU, Rep>>(q); return quantity_point_cast<quantity_point<rebind_point_origin_dimension<O, ToD>, ToU, Rep>>(q);
} }
/** /**
@@ -347,7 +349,8 @@ template<Kind ToK, Unit ToU, typename K, typename U, typename Rep>
template<typename CastSpec, typename PK, typename U, typename Rep> template<typename CastSpec, typename PK, typename U, typename Rep>
[[nodiscard]] constexpr QuantityPointKind auto quantity_point_kind_cast(const quantity_point_kind<PK, U, Rep>& qpk) [[nodiscard]] constexpr QuantityPointKind auto quantity_point_kind_cast(const quantity_point_kind<PK, U, Rep>& qpk)
requires requires { requires is_specialization_of<CastSpec, quantity_point_kind>; requires requires { requires is_specialization_of<CastSpec, quantity_point_kind>;
requires requires { quantity_kind_cast<typename CastSpec::quantity_kind_type>(qpk.relative()); }; } || requires requires { quantity_kind_cast<typename CastSpec::quantity_kind_type>(qpk.relative()); };
requires equivalent<typename PK::origin, typename CastSpec::point_kind_type::origin>; } ||
requires { requires PointKind<CastSpec> && UnitOf<U, typename CastSpec::dimension>; } || requires { requires PointKind<CastSpec> && UnitOf<U, typename CastSpec::dimension>; } ||
requires { quantity_kind_cast<CastSpec>(qpk.relative()); } // TODO: Simplify when Clang catches up. requires { quantity_kind_cast<CastSpec>(qpk.relative()); } // TODO: Simplify when Clang catches up.
{ {

View File

@@ -93,22 +93,25 @@ public:
quantity_kind(const quantity_kind&) = default; quantity_kind(const quantity_kind&) = default;
quantity_kind(quantity_kind&&) = default; quantity_kind(quantity_kind&&) = default;
template<safe_convertible_to_<rep> Value> template<typename T>
requires is_same_v<dimension, dim_one> && std::is_constructible_v<quantity_type, Value> requires
constexpr explicit quantity_kind(const Value& v) : q_(v) {} (Quantity<std::remove_cvref_t<T>> ||
QuantityLike<std::remove_cvref_t<T>> ||
template<typename Q> (Dimensionless<quantity_type> && !Quantity<std::remove_cvref_t<T>>)) &&
requires (Quantity<Q> || QuantityLike<Q>) && std::is_constructible_v<quantity_type, Q> std::constructible_from<quantity_type, T>
constexpr explicit quantity_kind(const Q& q) : q_{q} {} constexpr explicit quantity_kind(T&& t) : q_(std::forward<T>(t)) {}
template<QuantityKindEquivalentTo<quantity_kind> QK2> template<QuantityKindEquivalentTo<quantity_kind> QK2>
requires std::is_convertible_v<typename QK2::quantity_type, quantity_type> requires std::convertible_to<typename QK2::quantity_type, quantity_type>
constexpr explicit(false) quantity_kind(const QK2& qk) : q_{qk.common()} {} constexpr explicit(false) quantity_kind(const QK2& qk) : q_(qk.common()) {}
quantity_kind& operator=(const quantity_kind&) = default; quantity_kind& operator=(const quantity_kind&) = default;
quantity_kind& operator=(quantity_kind&&) = default; quantity_kind& operator=(quantity_kind&&) = default;
[[nodiscard]] constexpr quantity_type common() const noexcept { return q_; } [[nodiscard]] constexpr quantity_type& common() & noexcept { return q_; }
[[nodiscard]] constexpr const quantity_type& common() const & noexcept { return q_; }
[[nodiscard]] constexpr quantity_type&& common() && noexcept { return std::move(q_); }
[[nodiscard]] constexpr const quantity_type&& common() const && noexcept { return std::move(q_); }
[[nodiscard]] static constexpr quantity_kind zero() noexcept [[nodiscard]] static constexpr quantity_kind zero() noexcept
requires requires { quantity_type::zero(); } requires requires { quantity_type::zero(); }
@@ -225,19 +228,14 @@ public:
q_ %= rhs; q_ %= rhs;
return *this; return *this;
} }
template<typename Rep2>
constexpr quantity_kind& operator%=(const quantity_kind<downcast_kind<K, dim_one>, units::one, Rep2>& rhs)
requires requires(quantity_type q) { q %= rhs.common(); }
{
q_ %= rhs.common();
return *this;
}
constexpr quantity_kind& operator%=(const quantity_kind& qk) template<QuantityKind QK>
requires requires(quantity_type q) { q %= qk.common(); } constexpr quantity_kind& operator%=(const QK& rhs)
requires (QuantityKindEquivalentTo<QK, quantity_kind> || std::same_as<typename QK::kind_type, downcast_kind<K, dim_one>>) &&
requires(quantity_type q) { q %= rhs.common(); }
{ {
gsl_ExpectsAudit(qk.common().number() != quantity_values<rep>::zero()); gsl_ExpectsAudit(rhs.common().number() != quantity_values<typename QK::rep>::zero());
q_ %= qk.common(); q_ %= rhs.common();
return *this; return *this;
} }

View File

@@ -24,6 +24,7 @@
#pragma once #pragma once
// IWYU pragma: begin_exports // IWYU pragma: begin_exports
#include <units/point_origin.h>
#include <units/quantity.h> #include <units/quantity.h>
#include <compare> #include <compare>
// IWYU pragma: end_exports // IWYU pragma: end_exports
@@ -34,18 +35,32 @@
namespace units { namespace units {
/** /**
* @brief A quantity point * @brief A statically unspecified quantity point origin
* *
* An absolute quantity with respect to zero (which represents some origin). * An origin, unspecified in the type system, from which an absolute quantity is measured from.
* *
* @tparam D a dimension of the quantity point (can be either a BaseDimension or a DerivedDimension) * @tparam D a dimension of the quantity point (can be either a BaseDimension or a DerivedDimension)
*/
template<Dimension D>
struct dynamic_origin : point_origin<D> {
template<Dimension D2>
using rebind = dynamic_origin<D2>;
};
/**
* @brief A quantity point
*
* An absolute quantity measured from an origin.
*
* @tparam O a type that represents the origin from which the quantity point is measured from
* @tparam U a measurement unit of the quantity point * @tparam U a measurement unit of the quantity point
* @tparam Rep a type to be used to represent values of a quantity point * @tparam Rep a type to be used to represent values of a quantity point
*/ */
template<Dimension D, UnitOf<D> U, Representation Rep = double> template<PointOrigin O, UnitOf<typename O::dimension> U, Representation Rep = double>
class quantity_point { class quantity_point {
public: public:
using quantity_type = quantity<D, U, Rep>; using origin = O;
using quantity_type = quantity<typename origin::dimension, U, Rep>;
using dimension = typename quantity_type::dimension; using dimension = typename quantity_type::dimension;
using unit = typename quantity_type::unit; using unit = typename quantity_type::unit;
using rep = typename quantity_type::rep; using rep = typename quantity_type::rep;
@@ -59,29 +74,27 @@ public:
quantity_point(const quantity_point&) = default; quantity_point(const quantity_point&) = default;
quantity_point(quantity_point&&) = default; quantity_point(quantity_point&&) = default;
template<safe_convertible_to_<rep> Value> template<typename T>
requires is_same_v<dimension, dim_one> && std::is_constructible_v<quantity_type, Value> requires std::constructible_from<quantity_type, T>
constexpr explicit quantity_point(const Value& v) : q_(v) {} constexpr explicit quantity_point(T&& t) : q_(std::forward<T>(t)) {}
constexpr explicit quantity_point(const quantity_type& q) : q_{q} {} template<QuantityPointOf<origin> QP2>
requires std::convertible_to<typename QP2::quantity_type, quantity_type>
template<QuantityLike Q> constexpr explicit(false) quantity_point(const QP2& qp) : q_(qp.relative()) {}
requires std::is_constructible_v<quantity_type, Q>
constexpr explicit quantity_point(const Q& q) : q_{q} {}
template<QuantityPointLike QP> template<QuantityPointLike QP>
constexpr explicit quantity_point(const QP& qp) constexpr explicit quantity_point(const QP& qp)
requires std::is_constructible_v<quantity_type, decltype(quantity_point_like_traits<QP>::relative(qp))> requires std::is_constructible_v<quantity_type, decltype(quantity_point_like_traits<QP>::relative(qp))> &&
: q_{quantity_point_like_traits<QP>::relative(qp)} {} equivalent<origin, typename quantity_point_like_traits<QP>::origin>
: q_(quantity_point_like_traits<QP>::relative(qp)) {}
template<QuantityPoint QP2>
requires std::is_convertible_v<typename QP2::quantity_type, quantity_type>
constexpr explicit(false) quantity_point(const QP2& qp) : q_{qp.relative()} {}
quantity_point& operator=(const quantity_point&) = default; quantity_point& operator=(const quantity_point&) = default;
quantity_point& operator=(quantity_point&&) = default; quantity_point& operator=(quantity_point&&) = default;
[[nodiscard]] constexpr quantity_type relative() const noexcept { return q_; } [[nodiscard]] constexpr quantity_type& relative() & noexcept { return q_; }
[[nodiscard]] constexpr const quantity_type& relative() const & noexcept { return q_; }
[[nodiscard]] constexpr quantity_type&& relative() && noexcept { return std::move(q_); }
[[nodiscard]] constexpr const quantity_type&& relative() const && noexcept { return std::move(q_); }
[[nodiscard]] static constexpr quantity_point min() noexcept [[nodiscard]] static constexpr quantity_point min() noexcept
requires requires { quantity_type::min(); } requires requires { quantity_type::min(); }
@@ -144,7 +157,8 @@ public:
{ {
const auto q = lhs.relative() + rhs; const auto q = lhs.relative() + rhs;
using q_type = decltype(q); using q_type = decltype(q);
return quantity_point<typename q_type::dimension, typename q_type::unit, typename q_type::rep>(q); return quantity_point<rebind_point_origin_dimension<origin, typename q_type::dimension>, typename q_type::unit,
typename q_type::rep>(q);
} }
template<Quantity Q> template<Quantity Q>
@@ -160,48 +174,51 @@ public:
{ {
const auto q = lhs.relative() - rhs; const auto q = lhs.relative() - rhs;
using q_type = decltype(q); using q_type = decltype(q);
return quantity_point<typename q_type::dimension, typename q_type::unit, typename q_type::rep>(q); return quantity_point<rebind_point_origin_dimension<origin, typename q_type::dimension>, typename q_type::unit,
typename q_type::rep>(q);
} }
template<QuantityPoint QP> template<QuantityPointOf<origin> QP>
[[nodiscard]] friend constexpr Quantity auto operator-(const quantity_point& lhs, const QP& rhs) [[nodiscard]] friend constexpr Quantity auto operator-(const quantity_point& lhs, const QP& rhs)
requires requires(quantity_type q) { q - rhs.relative(); } requires requires(quantity_type q) { q - rhs.relative(); }
{ {
return lhs.relative() - rhs.relative(); return lhs.relative() - rhs.relative();
} }
template<QuantityPoint QP> template<QuantityPointOf<origin> QP>
requires std::three_way_comparable_with<quantity_type, typename QP::quantity_type> requires std::three_way_comparable_with<quantity_type, typename QP::quantity_type>
[[nodiscard]] friend constexpr auto operator<=>(const quantity_point& lhs, const QP& rhs) [[nodiscard]] friend constexpr auto operator<=>(const quantity_point& lhs, const QP& rhs)
{ {
return lhs.relative() <=> rhs.relative(); return lhs.relative() <=> rhs.relative();
} }
template<QuantityPoint QP> template<QuantityPointOf<origin> QP>
requires std::equality_comparable_with<quantity_type, typename QP::quantity_type> requires std::equality_comparable_with<quantity_type, typename QP::quantity_type>
[[nodiscard]] friend constexpr bool operator==(const quantity_point& lhs, const QP& rhs) [[nodiscard]] friend constexpr bool operator==(const quantity_point& lhs, const QP& rhs)
{ {
return lhs.relative() == rhs.relative(); return lhs.relative() == rhs.relative();
} }
}; };
template<Representation Rep> template<Representation Rep>
explicit(false) quantity_point(Rep) -> quantity_point<dim_one, one, Rep>; explicit quantity_point(Rep) -> quantity_point<dynamic_origin<dim_one>, one, Rep>;
template<Quantity Q>
explicit quantity_point(Q) -> quantity_point<dynamic_origin<typename Q::dimension>, typename Q::unit, typename Q::rep>;
template<QuantityLike Q> template<QuantityLike Q>
quantity_point(Q) -> quantity_point<typename quantity_like_traits<Q>::dimension, explicit quantity_point(Q) -> quantity_point<dynamic_origin<typename quantity_like_traits<Q>::dimension>,
typename quantity_like_traits<Q>::unit, typename quantity_like_traits<Q>::rep>; typename quantity_like_traits<Q>::unit, typename quantity_like_traits<Q>::rep>;
template<QuantityPointLike QP> template<QuantityPointLike QP>
explicit quantity_point(QP) -> quantity_point<typename quantity_point_like_traits<QP>::dimension, explicit quantity_point(QP) -> quantity_point<typename quantity_point_like_traits<QP>::origin,
typename quantity_point_like_traits<QP>::unit, typename quantity_point_like_traits<QP>::unit,
typename quantity_point_like_traits<QP>::rep>; typename quantity_point_like_traits<QP>::rep>;
namespace detail { namespace detail {
template<typename D, typename U, typename Rep> template<typename O, typename U, typename Rep>
inline constexpr bool is_quantity_point<quantity_point<D, U, Rep>> = true; inline constexpr bool is_quantity_point<quantity_point<O, U, Rep>> = true;
} // namespace detail } // namespace detail

View File

@@ -34,7 +34,7 @@ namespace units {
/** /**
* @brief A quantity point kind * @brief A quantity point kind
* *
* An absolute quantity kind with respect to zero (which represents some origin). * An absolute quantity kind measured from an origin.
* *
* @tparam PK the point kind of quantity point * @tparam PK the point kind of quantity point
* @tparam U the measurement unit of the quantity point kind * @tparam U the measurement unit of the quantity point kind
@@ -45,6 +45,7 @@ class quantity_point_kind {
public: public:
using point_kind_type = PK; using point_kind_type = PK;
using kind_type = typename PK::base_kind; using kind_type = typename PK::base_kind;
using origin = typename point_kind_type::origin;
using quantity_kind_type = quantity_kind<kind_type, U, Rep>; using quantity_kind_type = quantity_kind<kind_type, U, Rep>;
using quantity_type = typename quantity_kind_type::quantity_type; using quantity_type = typename quantity_kind_type::quantity_type;
using dimension = typename quantity_type::dimension; using dimension = typename quantity_type::dimension;
@@ -60,32 +61,28 @@ public:
quantity_point_kind(const quantity_point_kind&) = default; quantity_point_kind(const quantity_point_kind&) = default;
quantity_point_kind(quantity_point_kind&&) = default; quantity_point_kind(quantity_point_kind&&) = default;
template<safe_convertible_to_<rep> Value> template<typename T>
requires std::is_constructible_v<quantity_kind_type, Value> requires std::constructible_from<quantity_kind_type, T>
constexpr explicit quantity_point_kind(const Value& v) : qk_(v) {} constexpr explicit quantity_point_kind(T&& t) : qk_(std::forward<T>(t)) {}
constexpr explicit quantity_point_kind(const quantity_type& q) : qk_{q} {} constexpr explicit quantity_point_kind(const quantity_point<origin, U, Rep>& qp) : qk_(qp.relative()) {}
constexpr explicit quantity_point_kind(quantity_point<origin, U, Rep>&& qp) : qk_(std::move(qp).relative()) {}
template<QuantityLike Q>
requires std::is_constructible_v<quantity_type, Q>
constexpr explicit quantity_point_kind(const Q& q) : qk_{q} {}
template<QuantityPointLike QP> template<QuantityPointLike QP>
requires std::is_constructible_v<quantity_point<dimension, U, Rep>, QP> requires std::constructible_from<quantity_point<origin, U, Rep>, QP>
constexpr explicit quantity_point_kind(const QP& qp) : qk_{quantity_point_like_traits<QP>::relative(qp)} {} constexpr explicit quantity_point_kind(const QP& qp) : qk_(quantity_point_like_traits<QP>::relative(qp)) {}
constexpr explicit quantity_point_kind(const quantity_point<dimension, U, Rep>& qp) : qk_{qp.relative()} {} template<QuantityPointKindOf<point_kind_type> QPK2>
requires std::convertible_to<typename QPK2::quantity_kind_type, quantity_kind_type>
constexpr explicit quantity_point_kind(const quantity_kind_type& qk) : qk_{qk} {} constexpr explicit(false) quantity_point_kind(const QPK2& qpk) : qk_(qpk.relative()) {}
template<QuantityPointKindEquivalentTo<quantity_point_kind> QPK2>
requires std::is_convertible_v<typename QPK2::quantity_kind_type, quantity_kind_type>
constexpr explicit(false) quantity_point_kind(const QPK2& qpk) : qk_{qpk.relative()} {}
quantity_point_kind& operator=(const quantity_point_kind&) = default; quantity_point_kind& operator=(const quantity_point_kind&) = default;
quantity_point_kind& operator=(quantity_point_kind&&) = default; quantity_point_kind& operator=(quantity_point_kind&&) = default;
[[nodiscard]] constexpr quantity_kind_type relative() const noexcept { return qk_; } [[nodiscard]] constexpr quantity_kind_type& relative() & noexcept { return qk_; }
[[nodiscard]] constexpr const quantity_kind_type& relative() const & noexcept { return qk_; }
[[nodiscard]] constexpr quantity_kind_type&& relative() && noexcept { return std::move(qk_); }
[[nodiscard]] constexpr const quantity_kind_type&& relative() const && noexcept { return std::move(qk_); }
[[nodiscard]] static constexpr quantity_point_kind min() noexcept [[nodiscard]] static constexpr quantity_point_kind min() noexcept
requires requires { quantity_kind_type::min(); } requires requires { quantity_kind_type::min(); }
@@ -163,20 +160,21 @@ public:
return units::quantity_point_kind(lhs.relative() - rhs); return units::quantity_point_kind(lhs.relative() - rhs);
} }
[[nodiscard]] friend constexpr QuantityKind auto operator-(const quantity_point_kind& lhs, const quantity_point_kind& rhs) template<QuantityPointKindOf<point_kind_type> QPK>
[[nodiscard]] friend constexpr QuantityKind auto operator-(const quantity_point_kind& lhs, const QPK& rhs)
requires requires(quantity_kind_type qk) { qk - qk; } requires requires(quantity_kind_type qk) { qk - qk; }
{ {
return lhs.relative() - rhs.relative(); return lhs.relative() - rhs.relative();
} }
template<QuantityPointKind QPK> template<QuantityPointKindOf<point_kind_type> QPK>
requires std::three_way_comparable_with<quantity_kind_type, typename QPK::quantity_kind_type> requires std::three_way_comparable_with<quantity_kind_type, typename QPK::quantity_kind_type>
[[nodiscard]] friend constexpr auto operator<=>(const quantity_point_kind& lhs, const QPK& rhs) [[nodiscard]] friend constexpr auto operator<=>(const quantity_point_kind& lhs, const QPK& rhs)
{ {
return lhs.relative() <=> rhs.relative(); return lhs.relative() <=> rhs.relative();
} }
template<QuantityPointKind QPK> template<QuantityPointKindOf<point_kind_type> QPK>
requires std::equality_comparable_with<quantity_kind_type, typename QPK::quantity_kind_type> requires std::equality_comparable_with<quantity_kind_type, typename QPK::quantity_kind_type>
[[nodiscard]] friend constexpr bool operator==(const quantity_point_kind& lhs, const QPK& rhs) [[nodiscard]] friend constexpr bool operator==(const quantity_point_kind& lhs, const QPK& rhs)
{ {

View File

@@ -22,11 +22,11 @@
#pragma once #pragma once
#include <units/bits/deduced_symbol_text.h> #include <units/bits/derived_symbol_text.h>
#include <units/bits/external/downcasting.h> #include <units/bits/external/downcasting.h>
// IWYU pragma: begin_exports // IWYU pragma: begin_exports
#include <units/bits/deduced_unit.h> #include <units/bits/derived_unit.h>
#include <units/bits/external/fixed_string.h> #include <units/bits/external/fixed_string.h>
#include <units/prefix.h> #include <units/prefix.h>
#include <units/ratio.h> #include <units/ratio.h>
@@ -155,37 +155,12 @@ struct prefixed_unit : downcast_dispatch<Child, scaled_unit<P::ratio * U::ratio,
template<typename Child, DerivedDimension Dim, Unit U, Unit... URest> template<typename Child, DerivedDimension Dim, Unit U, Unit... URest>
requires detail::same_scaled_units<typename Dim::recipe, U, URest...> && requires detail::same_scaled_units<typename Dim::recipe, U, URest...> &&
(U::is_named && (URest::is_named && ... && true)) (U::is_named && (URest::is_named && ... && true))
struct deduced_unit : downcast_dispatch<Child, detail::deduced_unit<Dim, U, URest...>> { struct derived_unit : downcast_dispatch<Child, detail::derived_unit<Dim, U, URest...>> {
static constexpr bool is_named = false; static constexpr bool is_named = false;
static constexpr auto symbol = detail::deduced_symbol_text<Dim, U, URest...>(); static constexpr auto symbol = detail::derived_symbol_text<Dim, U, URest...>();
using prefix_family = no_prefix; using prefix_family = no_prefix;
}; };
/**
* @brief A unit with a deduced ratio and symbol that can be used as a named unit for children
*
* Defines a new unit with a deduced ratio and 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 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<typename Child, DerivedDimension Dim, Unit U, Unit... URest>
requires detail::same_scaled_units<typename Dim::recipe, U, URest...> &&
(U::is_named && (URest::is_named && ... && true))
// TODO - 'noble' is placeholder to sort of mean can pass its name on to other deduced units
struct noble_deduced_unit : downcast_dispatch<Child, detail::deduced_unit<Dim, U, URest...>> {
static constexpr bool is_named = true;
static constexpr auto symbol = detail::deduced_symbol_text<Dim, U, URest...>();
using prefix_family = no_prefix;
};
/** /**
* @brief A named unit with a deduced ratio * @brief A named unit with a deduced ratio
* *
@@ -203,7 +178,7 @@ struct noble_deduced_unit : downcast_dispatch<Child, detail::deduced_unit<Dim, U
*/ */
template<typename Child, DerivedDimension Dim, basic_symbol_text Symbol, PrefixFamily PF, Unit U, Unit... URest> template<typename Child, DerivedDimension Dim, basic_symbol_text Symbol, PrefixFamily PF, Unit U, Unit... URest>
requires detail::same_scaled_units<typename Dim::recipe, U, URest...> requires detail::same_scaled_units<typename Dim::recipe, U, URest...>
struct named_deduced_unit : downcast_dispatch<Child, detail::deduced_unit<Dim, U, URest...>> { struct named_derived_unit : downcast_dispatch<Child, detail::derived_unit<Dim, U, URest...>> {
static constexpr bool is_named = true; static constexpr bool is_named = true;
static constexpr auto symbol = Symbol; static constexpr auto symbol = Symbol;
using prefix_family = PF; using prefix_family = PF;

View File

@@ -50,7 +50,7 @@ using dim_modulation_rate = si::dim_frequency;
template<UnitOf<dim_modulation_rate> U, Representation Rep = double> template<UnitOf<dim_modulation_rate> U, Representation Rep = double>
using modulation_rate = quantity<dim_modulation_rate, U, Rep>; using modulation_rate = quantity<dim_modulation_rate, U, Rep>;
#ifdef UNITS_LITERALS #ifndef UNITS_NO_LITERALS
inline namespace literals { inline namespace literals {
@@ -66,9 +66,9 @@ constexpr auto operator"" _q_YBd(unsigned long long l) { gsl_ExpectsAudit(std::i
} // namespace literals } // namespace literals
#endif // UNITS_LITERALS #endif // UNITS_NO_LITERALS
#ifdef UNITS_REFERENCES #ifndef UNITS_NO_REFERENCES
namespace modulation_rate_references { namespace modulation_rate_references {
@@ -90,11 +90,11 @@ using namespace modulation_rate_references;
} // namespace references } // namespace references
#endif // UNITS_REFERENCES #endif // UNITS_NO_REFERENCES
} // namespace units::isq::iec80000 } // namespace units::isq::iec80000
#ifdef UNITS_ALIASES #ifndef UNITS_NO_ALIASES
namespace units::aliases::isq::iec80000::inline modulation_rate { namespace units::aliases::isq::iec80000::inline modulation_rate {
@@ -110,4 +110,4 @@ template<Representation Rep = double> using YBd = units::isq::iec80000::modulati
} // namespace units::aliases::isq::iec80000::inline modulation_rate } // namespace units::aliases::isq::iec80000::inline modulation_rate
#endif // UNITS_ALIASES #endif // UNITS_NO_ALIASES

View File

@@ -79,7 +79,7 @@ concept StorageCapacity = QuantityOf<T, dim_storage_capacity>;
template<UnitOf<dim_storage_capacity> U, Representation Rep = double> template<UnitOf<dim_storage_capacity> U, Representation Rep = double>
using storage_capacity = quantity<dim_storage_capacity, U, Rep>; using storage_capacity = quantity<dim_storage_capacity, U, Rep>;
#ifdef UNITS_LITERALS #ifndef UNITS_NO_LITERALS
inline namespace literals { inline namespace literals {
@@ -123,9 +123,9 @@ constexpr auto operator"" _q_PiB(unsigned long long l) { gsl_ExpectsAudit(std::i
} // namespace literals } // namespace literals
#endif // UNITS_LITERALS #endif // UNITS_NO_LITERALS
#ifdef UNITS_REFERENCES #ifndef UNITS_NO_REFERENCES
namespace storage_capacity_references { namespace storage_capacity_references {
@@ -175,11 +175,11 @@ using namespace storage_capacity_references;
} // namespace references } // namespace references
#endif // UNITS_REFERENCES #endif // UNITS_NO_REFERENCES
} // namespace units::isq::iec80000 } // namespace units::isq::iec80000
#ifdef UNITS_ALIASES #ifndef UNITS_NO_ALIASES
namespace units::aliases::isq::iec80000::inline storage_capacity { namespace units::aliases::isq::iec80000::inline storage_capacity {
@@ -223,4 +223,4 @@ template<Representation Rep = double> using PiB = units::isq::iec80000::storage_
} // namespace units::aliases::isq::iec80000::inline storage_capacity } // namespace units::aliases::isq::iec80000::inline storage_capacity
#endif // UNITS_ALIASES #endif // UNITS_NO_ALIASES

View File

@@ -43,7 +43,7 @@ concept TrafficIntensity = QuantityOf<T, dim_traffic_intensity>;
template<UnitOf<dim_traffic_intensity> U, Representation Rep = double> template<UnitOf<dim_traffic_intensity> U, Representation Rep = double>
using traffic_intensity = quantity<dim_traffic_intensity, U, Rep>; using traffic_intensity = quantity<dim_traffic_intensity, U, Rep>;
#ifdef UNITS_LITERALS #ifndef UNITS_NO_LITERALS
inline namespace literals { inline namespace literals {
@@ -51,9 +51,9 @@ constexpr auto operator"" _q_E(unsigned long long l) { gsl_ExpectsAudit(std::in_
} // namespace literals } // namespace literals
#endif // UNITS_LITERALS #endif // UNITS_NO_LITERALS
#ifdef UNITS_REFERENCES #ifndef UNITS_NO_REFERENCES
namespace traffic_intensity_references { namespace traffic_intensity_references {
@@ -67,11 +67,11 @@ using namespace traffic_intensity_references;
} // namespace references } // namespace references
#endif // UNITS_REFERENCES #endif // UNITS_NO_REFERENCES
} // namespace units::isq::iec80000 } // namespace units::isq::iec80000
#ifdef UNITS_ALIASES #ifndef UNITS_NO_ALIASES
namespace units::aliases::isq::iec80000::inline traffic_intensity { namespace units::aliases::isq::iec80000::inline traffic_intensity {
@@ -79,4 +79,4 @@ template<Representation Rep = double> using E = units::isq::iec80000::traffic_in
} // namespace units::aliases::isq::iec80000::inline traffic_intensity } // namespace units::aliases::isq::iec80000::inline traffic_intensity
#endif // UNITS_ALIASES #endif // UNITS_NO_ALIASES

View File

@@ -37,14 +37,14 @@ namespace units::isq::iec80000 {
struct byte_per_second : unit<byte_per_second> {}; struct byte_per_second : unit<byte_per_second> {};
struct dim_transfer_rate : derived_dimension<dim_transfer_rate, byte_per_second, exponent<dim_storage_capacity, 1>, exponent<si::dim_time, -1>> {}; struct dim_transfer_rate : derived_dimension<dim_transfer_rate, byte_per_second, exponent<dim_storage_capacity, 1>, exponent<si::dim_time, -1>> {};
struct kilobyte_per_second : deduced_unit<kilobyte_per_second, dim_transfer_rate, kilobyte, si::second> {}; struct kilobyte_per_second : derived_unit<kilobyte_per_second, dim_transfer_rate, kilobyte, si::second> {};
struct megabyte_per_second : deduced_unit<megabyte_per_second, dim_transfer_rate, megabyte, si::second> {}; struct megabyte_per_second : derived_unit<megabyte_per_second, dim_transfer_rate, megabyte, si::second> {};
struct gigabyte_per_second : deduced_unit<gigabyte_per_second, dim_transfer_rate, gigabyte, si::second> {}; struct gigabyte_per_second : derived_unit<gigabyte_per_second, dim_transfer_rate, gigabyte, si::second> {};
struct terabyte_per_second : deduced_unit<terabyte_per_second, dim_transfer_rate, terabyte, si::second> {}; struct terabyte_per_second : derived_unit<terabyte_per_second, dim_transfer_rate, terabyte, si::second> {};
struct petabyte_per_second : deduced_unit<petabyte_per_second, dim_transfer_rate, petabyte, si::second> {}; struct petabyte_per_second : derived_unit<petabyte_per_second, dim_transfer_rate, petabyte, si::second> {};
struct exabyte_per_second : deduced_unit<exabyte_per_second, dim_transfer_rate, exabyte, si::second> {}; struct exabyte_per_second : derived_unit<exabyte_per_second, dim_transfer_rate, exabyte, si::second> {};
struct zettabyte_per_second : deduced_unit<zettabyte_per_second, dim_transfer_rate, zettabyte, si::second> {}; struct zettabyte_per_second : derived_unit<zettabyte_per_second, dim_transfer_rate, zettabyte, si::second> {};
struct yottabyte_per_second : deduced_unit<yottabyte_per_second, dim_transfer_rate, yottabyte, si::second> {}; struct yottabyte_per_second : derived_unit<yottabyte_per_second, dim_transfer_rate, yottabyte, si::second> {};
template<typename T> template<typename T>
concept TransferRate = QuantityOf<T, dim_transfer_rate>; concept TransferRate = QuantityOf<T, dim_transfer_rate>;
@@ -52,7 +52,7 @@ concept TransferRate = QuantityOf<T, dim_transfer_rate>;
template<UnitOf<dim_transfer_rate> U, Representation Rep = double> template<UnitOf<dim_transfer_rate> U, Representation Rep = double>
using transfer_rate = quantity<dim_transfer_rate, U, Rep>; using transfer_rate = quantity<dim_transfer_rate, U, Rep>;
#ifdef UNITS_LITERALS #ifndef UNITS_NO_LITERALS
inline namespace literals { inline namespace literals {
@@ -68,11 +68,11 @@ constexpr auto operator"" _q_YB_per_s(unsigned long long l) { gsl_ExpectsAudit(s
} // namespace literals } // namespace literals
#endif // UNITS_LITERALS #endif // UNITS_NO_LITERALS
} // namespace units::isq::iec80000 } // namespace units::isq::iec80000
#ifdef UNITS_ALIASES #ifndef UNITS_NO_ALIASES
namespace units::aliases::isq::iec80000::inline transfer_rate { namespace units::aliases::isq::iec80000::inline transfer_rate {
@@ -88,4 +88,4 @@ template<Representation Rep = double> using YB_per_s = units::isq::iec80000::tra
} // namespace units::aliases::isq::iec80000::inline transfer_rate } // namespace units::aliases::isq::iec80000::inline transfer_rate
#endif // UNITS_ALIASES #endif // UNITS_NO_ALIASES

View File

@@ -40,7 +40,7 @@ struct dim_acceleration : isq::dim_acceleration<dim_acceleration, gigaelectronvo
template<UnitOf<dim_acceleration> U, Representation Rep = double> template<UnitOf<dim_acceleration> U, Representation Rep = double>
using acceleration = quantity<dim_acceleration, U, Rep>; using acceleration = quantity<dim_acceleration, U, Rep>;
#ifdef UNITS_REFERENCES #ifndef UNITS_NO_REFERENCES
namespace acceleration_references { namespace acceleration_references {
@@ -54,11 +54,11 @@ using namespace acceleration_references;
} // namespace references } // namespace references
#endif // UNITS_REFERENCES #endif // UNITS_NO_REFERENCES
} // namespace units::isq::natural } // namespace units::isq::natural
#ifdef UNITS_ALIASES #ifndef UNITS_NO_ALIASES
namespace units::aliases::isq::natural::inline acceleration { namespace units::aliases::isq::natural::inline acceleration {
@@ -66,4 +66,4 @@ template<Representation Rep = double> using GeV = units::isq::natural::accelerat
} // namespace units::aliases::isq::natural::inline acceleration } // namespace units::aliases::isq::natural::inline acceleration
#endif // UNITS_ALIASES #endif // UNITS_NO_ALIASES

View File

@@ -40,7 +40,7 @@ struct dim_energy : isq::dim_energy<dim_energy, gigaelectronvolt, dim_force, dim
template<UnitOf<dim_energy> U, Representation Rep = double> template<UnitOf<dim_energy> U, Representation Rep = double>
using energy = quantity<dim_energy, U, Rep>; using energy = quantity<dim_energy, U, Rep>;
#ifdef UNITS_REFERENCES #ifndef UNITS_NO_REFERENCES
namespace energy_references { namespace energy_references {
@@ -54,11 +54,11 @@ using namespace energy_references;
} // namespace references } // namespace references
#endif // UNITS_REFERENCES #endif // UNITS_NO_REFERENCES
} // namespace units::isq::natural } // namespace units::isq::natural
#ifdef UNITS_ALIASES #ifndef UNITS_NO_ALIASES
namespace units::aliases::isq::natural::inline energy { namespace units::aliases::isq::natural::inline energy {
@@ -66,4 +66,4 @@ template<Representation Rep = double> using GeV = units::isq::natural::energy<un
} // namespace units::aliases::isq::natural::inline energy } // namespace units::aliases::isq::natural::inline energy
#endif // UNITS_ALIASES #endif // UNITS_NO_ALIASES

View File

@@ -40,7 +40,7 @@ struct dim_force : isq::dim_force<dim_force, square_gigaelectronvolt, dim_mass,
template<UnitOf<dim_force> U, Representation Rep = double> template<UnitOf<dim_force> U, Representation Rep = double>
using force = quantity<dim_force, U, Rep>; using force = quantity<dim_force, U, Rep>;
#ifdef UNITS_REFERENCES #ifndef UNITS_NO_REFERENCES
namespace force_references { namespace force_references {
@@ -54,11 +54,11 @@ using namespace force_references;
} // namespace references } // namespace references
#endif // UNITS_REFERENCES #endif // UNITS_NO_REFERENCES
} // namespace units::isq::natural } // namespace units::isq::natural
#ifdef UNITS_ALIASES #ifndef UNITS_NO_ALIASES
namespace units::aliases::isq::natural::inline force { namespace units::aliases::isq::natural::inline force {
@@ -66,4 +66,4 @@ template<Representation Rep = double> using GeV2 = units::isq::natural::force<un
} // namespace units::aliases::isq::natural::inline force } // namespace units::aliases::isq::natural::inline force
#endif // UNITS_ALIASES #endif // UNITS_NO_ALIASES

View File

@@ -37,7 +37,7 @@ struct dim_length : isq::dim_length<inverted_gigaelectronvolt> {};
template<UnitOf<dim_length> U, Representation Rep = double> template<UnitOf<dim_length> U, Representation Rep = double>
using length = quantity<dim_length, U, Rep>; using length = quantity<dim_length, U, Rep>;
#ifdef UNITS_REFERENCES #ifndef UNITS_NO_REFERENCES
namespace length_references { namespace length_references {
@@ -51,11 +51,11 @@ using namespace length_references;
} // namespace references } // namespace references
#endif // UNITS_REFERENCES #endif // UNITS_NO_REFERENCES
} // namespace units::isq::natural } // namespace units::isq::natural
#ifdef UNITS_ALIASES #ifndef UNITS_NO_ALIASES
namespace units::aliases::isq::natural::inline length { namespace units::aliases::isq::natural::inline length {
@@ -63,4 +63,4 @@ template<Representation Rep = double> using inv_GeV = units::isq::natural::lengt
} // namespace units::aliases::isq::natural::inline length } // namespace units::aliases::isq::natural::inline length
#endif // UNITS_ALIASES #endif // UNITS_NO_ALIASES

View File

@@ -37,7 +37,7 @@ struct dim_mass : isq::dim_mass<gigaelectronvolt> {};
template<UnitOf<dim_mass> U, Representation Rep = double> template<UnitOf<dim_mass> U, Representation Rep = double>
using mass = quantity<dim_mass, U, Rep>; using mass = quantity<dim_mass, U, Rep>;
#ifdef UNITS_REFERENCES #ifndef UNITS_NO_REFERENCES
namespace mass_references { namespace mass_references {
@@ -51,11 +51,11 @@ using namespace mass_references;
} // namespace references } // namespace references
#endif // UNITS_REFERENCES #endif // UNITS_NO_REFERENCES
} // namespace units::isq::natural } // namespace units::isq::natural
#ifdef UNITS_ALIASES #ifndef UNITS_NO_ALIASES
namespace units::aliases::isq::natural::inline mass { namespace units::aliases::isq::natural::inline mass {
@@ -63,4 +63,4 @@ template<Representation Rep = double> using GeV = units::isq::natural::mass<unit
} // namespace units::aliases::isq::natural::inline mass } // namespace units::aliases::isq::natural::inline mass
#endif // UNITS_ALIASES #endif // UNITS_NO_ALIASES

View File

@@ -40,7 +40,7 @@ struct dim_momentum : isq::dim_momentum<dim_momentum, gigaelectronvolt, dim_mass
template<UnitOf<dim_momentum> U, Representation Rep = double> template<UnitOf<dim_momentum> U, Representation Rep = double>
using momentum = quantity<dim_momentum, U, Rep>; using momentum = quantity<dim_momentum, U, Rep>;
#ifdef UNITS_REFERENCES #ifndef UNITS_NO_REFERENCES
namespace momentum_references { namespace momentum_references {
@@ -54,11 +54,11 @@ using namespace momentum_references;
} // namespace references } // namespace references
#endif // UNITS_REFERENCES #endif // UNITS_NO_REFERENCES
} // namespace units::isq::natural } // namespace units::isq::natural
#ifdef UNITS_ALIASES #ifndef UNITS_NO_ALIASES
namespace units::aliases::isq::natural::inline momentum { namespace units::aliases::isq::natural::inline momentum {
@@ -66,4 +66,4 @@ template<Representation Rep = double> using GeV = units::isq::natural::momentum<
} // namespace units::aliases::isq::natural::inline momentum } // namespace units::aliases::isq::natural::inline momentum
#endif // UNITS_ALIASES #endif // UNITS_NO_ALIASES

View File

@@ -37,7 +37,7 @@ struct dim_time : isq::dim_time<inverted_gigaelectronvolt> {};
template<UnitOf<dim_time> U, Representation Rep = double> template<UnitOf<dim_time> U, Representation Rep = double>
using time = quantity<dim_time, U, Rep>; using time = quantity<dim_time, U, Rep>;
#ifdef UNITS_REFERENCES #ifndef UNITS_NO_REFERENCES
namespace time_references { namespace time_references {
@@ -51,11 +51,11 @@ using namespace time_references;
} // namespace references } // namespace references
#endif // UNITS_REFERENCES #endif // UNITS_NO_REFERENCES
} // namespace units::isq::natural } // namespace units::isq::natural
#ifdef UNITS_ALIASES #ifndef UNITS_NO_ALIASES
namespace units::aliases::isq::natural::inline time { namespace units::aliases::isq::natural::inline time {
@@ -63,4 +63,4 @@ template<Representation Rep = double> using inv_GeV = units::isq::natural::time<
} // namespace units::aliases::isq::natural::inline time } // namespace units::aliases::isq::natural::inline time
#endif // UNITS_ALIASES #endif // UNITS_NO_ALIASES

View File

@@ -28,8 +28,11 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, typename...>
struct dim_absorbed_dose;
template<typename Child, Unit U, DimensionOfT<dim_energy> E, DimensionOfT<dim_mass> M> template<typename Child, Unit U, DimensionOfT<dim_energy> E, DimensionOfT<dim_mass> M>
struct dim_absorbed_dose : derived_dimension<Child, U, exponent<E, 1>, exponent<M, -1>> {}; struct dim_absorbed_dose<Child, U, E, M> : derived_dimension<Child, U, exponent<E, 1>, exponent<M, -1>> {};
template<typename T> template<typename T>
concept AbsorbedDose = QuantityOfT<T, dim_absorbed_dose>; concept AbsorbedDose = QuantityOfT<T, dim_absorbed_dose>;

View File

@@ -28,8 +28,11 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, typename...>
struct dim_acceleration;
template<typename Child, Unit U, DimensionOfT<dim_length> L, DimensionOfT<dim_time> T> template<typename Child, Unit U, DimensionOfT<dim_length> L, DimensionOfT<dim_time> T>
struct dim_acceleration : derived_dimension<Child, U, exponent<L, 1>, exponent<T, -2>> {}; struct dim_acceleration<Child, U, L, T> : derived_dimension<Child, U, exponent<L, 1>, exponent<T, -2>> {};
template<typename T> template<typename T>
concept Acceleration = QuantityOfT<T, dim_acceleration>; concept Acceleration = QuantityOfT<T, dim_acceleration>;

View File

@@ -28,8 +28,11 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, typename...>
struct dim_angular_velocity;
template<typename Child, Unit U, DimensionOfT<dim_angle> A, DimensionOfT<dim_time> T> template<typename Child, Unit U, DimensionOfT<dim_angle> A, DimensionOfT<dim_time> T>
struct dim_angular_velocity : derived_dimension<Child, U, exponent<A, 1>, exponent<T, -1>> {}; struct dim_angular_velocity<Child, U, A, T> : derived_dimension<Child, U, exponent<A, 1>, exponent<T, -1>> {};
template <typename T> template <typename T>
concept AngularVelocity = QuantityOfT<T, dim_angular_velocity>; concept AngularVelocity = QuantityOfT<T, dim_angular_velocity>;

View File

@@ -27,8 +27,11 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, typename...>
struct dim_area;
template<typename Child, Unit U, DimensionOfT<dim_length> L> template<typename Child, Unit U, DimensionOfT<dim_length> L>
struct dim_area : derived_dimension<Child, U, exponent<L, 2>> {}; struct dim_area<Child, U, L> : derived_dimension<Child, U, exponent<L, 2>> {};
template<typename T> template<typename T>
concept Area = QuantityOfT<T, dim_area>; concept Area = QuantityOfT<T, dim_area>;

View File

@@ -28,8 +28,11 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, typename...>
struct dim_capacitance;
template<typename Child, Unit U, DimensionOfT<dim_electric_charge> C, DimensionOfT<dim_voltage> V> template<typename Child, Unit U, DimensionOfT<dim_electric_charge> C, DimensionOfT<dim_voltage> V>
struct dim_capacitance : derived_dimension<Child, U, exponent<C, 1>, exponent<V, -1>> {}; struct dim_capacitance<Child, U, C, V> : derived_dimension<Child, U, exponent<C, 1>, exponent<V, -1>> {};
template<typename T> template<typename T>
concept Capacitance = QuantityOfT<T, dim_capacitance>; concept Capacitance = QuantityOfT<T, dim_capacitance>;

View File

@@ -28,8 +28,11 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, typename...>
struct dim_catalytic_activity;
template<typename Child, Unit U, DimensionOfT<dim_time> T, DimensionOfT<dim_amount_of_substance> M> template<typename Child, Unit U, DimensionOfT<dim_time> T, DimensionOfT<dim_amount_of_substance> M>
struct dim_catalytic_activity : derived_dimension<Child, U, exponent<T, -1>, exponent<M, 1>> {}; struct dim_catalytic_activity<Child, U, T, M> : derived_dimension<Child, U, exponent<T, -1>, exponent<M, 1>> {};
template<typename T> template<typename T>
concept CatalyticActivity = QuantityOfT<T, dim_catalytic_activity>; concept CatalyticActivity = QuantityOfT<T, dim_catalytic_activity>;

View File

@@ -28,11 +28,17 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, DimensionOfT<dim_electric_charge> Q, DimensionOfT<dim_length> L> template<typename Child, Unit U, typename...>
struct dim_charge_density : derived_dimension<Child, U, exponent<Q, 1>, exponent<L, -3>> {}; struct dim_charge_density;
template<typename Child, Unit U, DimensionOfT<dim_electric_charge> Q, DimensionOfT<dim_length> L> template<typename Child, Unit U, DimensionOfT<dim_electric_charge> Q, DimensionOfT<dim_length> L>
struct dim_surface_charge_density : derived_dimension<Child, U, exponent<Q, 1>, exponent<L, -2>> {}; struct dim_charge_density<Child, U, Q, L> : derived_dimension<Child, U, exponent<Q, 1>, exponent<L, -3>> {};
template<typename Child, Unit U, typename...>
struct dim_surface_charge_density;
template<typename Child, Unit U, DimensionOfT<dim_electric_charge> Q, DimensionOfT<dim_length> L>
struct dim_surface_charge_density<Child, U, Q, L> : derived_dimension<Child, U, exponent<Q, 1>, exponent<L, -2>> {};
template<typename T> template<typename T>
concept ChargeDensity = QuantityOfT<T, dim_charge_density>; concept ChargeDensity = QuantityOfT<T, dim_charge_density>;

View File

@@ -28,8 +28,11 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, typename...>
struct dim_concentration;
template<typename Child, Unit U, DimensionOfT<dim_amount_of_substance> M, DimensionOfT<dim_length> L> template<typename Child, Unit U, DimensionOfT<dim_amount_of_substance> M, DimensionOfT<dim_length> L>
struct dim_concentration : derived_dimension<Child, U, exponent<M, 1>, exponent<L, -3>> {}; struct dim_concentration<Child, U, M, L> : derived_dimension<Child, U, exponent<M, 1>, exponent<L, -3>> {};
template<typename T> template<typename T>
concept Concentration = QuantityOfT<T, dim_concentration>; concept Concentration = QuantityOfT<T, dim_concentration>;

View File

@@ -27,8 +27,11 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, typename...>
struct dim_conductance;
template<typename Child, Unit U, DimensionOfT<dim_resistance> R> template<typename Child, Unit U, DimensionOfT<dim_resistance> R>
struct dim_conductance : derived_dimension<Child, U, exponent<R, -1>> {}; struct dim_conductance<Child, U, R> : derived_dimension<Child, U, exponent<R, -1>> {};
template<typename T> template<typename T>
concept Conductance = QuantityOfT<T, dim_conductance>; concept Conductance = QuantityOfT<T, dim_conductance>;

View File

@@ -28,8 +28,11 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, typename...>
struct dim_current_density;
template<typename Child, Unit U, DimensionOfT<dim_electric_current> I, DimensionOfT<dim_length> L> template<typename Child, Unit U, DimensionOfT<dim_electric_current> I, DimensionOfT<dim_length> L>
struct dim_current_density : derived_dimension<Child, U, exponent<I, 1>, exponent<L, -2>> {}; struct dim_current_density<Child, U, I, L> : derived_dimension<Child, U, exponent<I, 1>, exponent<L, -2>> {};
template<typename T> template<typename T>
concept CurrentDensity = QuantityOfT<T, dim_current_density>; concept CurrentDensity = QuantityOfT<T, dim_current_density>;

View File

@@ -28,8 +28,11 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, typename...>
struct dim_density;
template<typename Child, Unit U, DimensionOfT<dim_mass> M, DimensionOfT<dim_length> L> template<typename Child, Unit U, DimensionOfT<dim_mass> M, DimensionOfT<dim_length> L>
struct dim_density : derived_dimension<Child, U, exponent<M, 1>, exponent<L, -3>> {}; struct dim_density<Child, U, M, L> : derived_dimension<Child, U, exponent<M, 1>, exponent<L, -3>> {};
template<typename T> template<typename T>
concept Density = QuantityOfT<T, dim_density>; concept Density = QuantityOfT<T, dim_density>;

View File

@@ -28,8 +28,11 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, typename...>
struct dim_dynamic_viscosity;
template<typename Child, Unit U, DimensionOfT<dim_pressure> P, DimensionOfT<dim_time> T> template<typename Child, Unit U, DimensionOfT<dim_pressure> P, DimensionOfT<dim_time> T>
struct dim_dynamic_viscosity : derived_dimension<Child, U, exponent<P, 1>, exponent<T, 1>> {}; struct dim_dynamic_viscosity<Child, U, P, T> : derived_dimension<Child, U, exponent<P, 1>, exponent<T, 1>> {};
template<typename T> template<typename T>
concept DynamicViscosity = QuantityOfT<T, dim_dynamic_viscosity>; concept DynamicViscosity = QuantityOfT<T, dim_dynamic_viscosity>;

View File

@@ -28,8 +28,11 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, typename...>
struct dim_electric_charge;
template<typename Child, Unit U, DimensionOfT<dim_time> T, DimensionOfT<dim_electric_current> C> template<typename Child, Unit U, DimensionOfT<dim_time> T, DimensionOfT<dim_electric_current> C>
struct dim_electric_charge : derived_dimension<Child, U, exponent<T, 1>, exponent<C, 1>> {}; struct dim_electric_charge<Child, U, T, C> : derived_dimension<Child, U, exponent<T, 1>, exponent<C, 1>> {};
template<typename T> template<typename T>
concept ElectricCharge = QuantityOfT<T, dim_electric_charge>; concept ElectricCharge = QuantityOfT<T, dim_electric_charge>;

View File

@@ -28,8 +28,11 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, typename...>
struct dim_electric_field_strength;
template<typename Child, Unit U, DimensionOfT<dim_voltage> V, DimensionOfT<dim_length> L> template<typename Child, Unit U, DimensionOfT<dim_voltage> V, DimensionOfT<dim_length> L>
struct dim_electric_field_strength : derived_dimension<Child, U, exponent<V, 1>, exponent<L, -1>> {}; struct dim_electric_field_strength<Child, U, V, L> : derived_dimension<Child, U, exponent<V, 1>, exponent<L, -1>> {};
template<typename T> template<typename T>
concept ElectricFieldStrength = QuantityOfT<T, dim_electric_field_strength>; concept ElectricFieldStrength = QuantityOfT<T, dim_electric_field_strength>;

View File

@@ -28,8 +28,14 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, typename...>
struct dim_energy;
template<typename Child, Unit U, DimensionOfT<dim_force> F, DimensionOfT<dim_length> L> template<typename Child, Unit U, DimensionOfT<dim_force> F, DimensionOfT<dim_length> L>
struct dim_energy : derived_dimension<Child, U, exponent<F, 1>, exponent<L, 1>> {}; struct dim_energy<Child, U, F, L> : derived_dimension<Child, U, exponent<F, 1>, exponent<L, 1>> {};
template<typename Child, Unit U, DimensionOfT<dim_length> L, DimensionOfT<dim_force> F>
struct dim_energy<Child, U, L, F> : derived_dimension<Child, U, exponent<L, 1>, exponent<F, 1>> {};
template<typename T> template<typename T>
concept Energy = QuantityOfT<T, dim_energy>; concept Energy = QuantityOfT<T, dim_energy>;

View File

@@ -28,8 +28,11 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, typename...>
struct dim_energy_density;
template<typename Child, Unit U, DimensionOfT<dim_energy> E, DimensionOfT<dim_volume> V> template<typename Child, Unit U, DimensionOfT<dim_energy> E, DimensionOfT<dim_volume> V>
struct dim_energy_density : derived_dimension<Child, U, exponent<E, 1>, exponent<V, -1>> {}; struct dim_energy_density<Child, U, E, V> : derived_dimension<Child, U, exponent<E, 1>, exponent<V, -1>> {};
template<typename T> template<typename T>
concept EnergyDensity = QuantityOfT<T, dim_energy_density>; concept EnergyDensity = QuantityOfT<T, dim_energy_density>;

View File

@@ -28,8 +28,11 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, typename...>
struct dim_force;
template<typename Child, Unit U, DimensionOfT<dim_mass> M, DimensionOfT<dim_acceleration> A> template<typename Child, Unit U, DimensionOfT<dim_mass> M, DimensionOfT<dim_acceleration> A>
struct dim_force : derived_dimension<Child, U, exponent<M, 1>, exponent<A, 1>> {}; struct dim_force<Child, U, M, A> : derived_dimension<Child, U, exponent<M, 1>, exponent<A, 1>> {};
template<typename T> template<typename T>
concept Force = QuantityOfT<T, dim_force>; concept Force = QuantityOfT<T, dim_force>;

View File

@@ -27,8 +27,11 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, typename...>
struct dim_frequency;
template<typename Child, Unit U, DimensionOfT<dim_time> T> template<typename Child, Unit U, DimensionOfT<dim_time> T>
struct dim_frequency : derived_dimension<Child, U, exponent<T, -1>> {}; struct dim_frequency<Child, U, T> : derived_dimension<Child, U, exponent<T, -1>> {};
template<typename T> template<typename T>
concept Frequency = QuantityOfT<T, dim_frequency>; concept Frequency = QuantityOfT<T, dim_frequency>;

View File

@@ -30,14 +30,23 @@
namespace units::isq { namespace units::isq {
template<typename Child, Unit U, typename...>
struct dim_heat_capacity;
template<typename Child, Unit U, DimensionOfT<dim_energy> E, DimensionOfT<dim_thermodynamic_temperature> T> template<typename Child, Unit U, DimensionOfT<dim_energy> E, DimensionOfT<dim_thermodynamic_temperature> T>
struct dim_heat_capacity : derived_dimension<Child, U, exponent<E, 1>, exponent<T, -1>> {}; struct dim_heat_capacity<Child, U, E, T> : derived_dimension<Child, U, exponent<E, 1>, exponent<T, -1>> {};
template<typename Child, Unit U, typename...>
struct dim_specific_heat_capacity;
template<typename Child, Unit U, DimensionOfT<dim_heat_capacity> C, DimensionOfT<dim_mass> M> template<typename Child, Unit U, DimensionOfT<dim_heat_capacity> C, DimensionOfT<dim_mass> M>
struct dim_specific_heat_capacity : derived_dimension<Child, U, exponent<C, 1>, exponent<M, -1>> {}; struct dim_specific_heat_capacity<Child, U, C, M> : derived_dimension<Child, U, exponent<C, 1>, exponent<M, -1>> {};
template<typename Child, Unit U, typename...>
struct dim_molar_heat_capacity;
template<typename Child, Unit U, DimensionOfT<dim_heat_capacity> C, DimensionOfT<dim_amount_of_substance> M> template<typename Child, Unit U, DimensionOfT<dim_heat_capacity> C, DimensionOfT<dim_amount_of_substance> M>
struct dim_molar_heat_capacity : derived_dimension<Child, U, exponent<C, 1>, exponent<M, -1>> {}; struct dim_molar_heat_capacity<Child, U, C, M> : derived_dimension<Child, U, exponent<C, 1>, exponent<M, -1>> {};
template<typename T> template<typename T>
concept HeatCapacity = QuantityOfT<T, dim_heat_capacity>; concept HeatCapacity = QuantityOfT<T, dim_heat_capacity>;

Some files were not shown because too many files have changed in this diff Show More