mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-05 21:24:27 +02:00
Merge branch 'mpusz:master' into master
This commit is contained in:
@@ -63,7 +63,7 @@ CommentPragmas: '^ NOLINT'
|
||||
# CompactNamespaces: false
|
||||
# ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
# ConstructorInitializerIndentWidth: 4
|
||||
# ContinuationIndentWidth: 4
|
||||
ContinuationIndentWidth: 2
|
||||
# Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: false
|
||||
DerivePointerAlignment: false
|
||||
@@ -109,7 +109,7 @@ IndentRequires: true
|
||||
# KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
# MacroBlockBegin: ''
|
||||
# MacroBlockEnd: ''
|
||||
# MaxEmptyLinesToKeep: 1
|
||||
MaxEmptyLinesToKeep: 2
|
||||
# NamespaceIndentation: None
|
||||
# ObjCBinPackProtocolList: Never
|
||||
# ObjCBlockIndentWidth: 2
|
||||
|
11
.github/workflows/ci-conan.yml
vendored
11
.github/workflows/ci-conan.yml
vendored
@@ -78,6 +78,11 @@ jobs:
|
||||
downcast_mode: [ "on", "auto" ]
|
||||
steps:
|
||||
- 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
|
||||
if: matrix.config.compiler.type == 'CLANG'
|
||||
shell: bash
|
||||
@@ -121,12 +126,6 @@ jobs:
|
||||
conan profile update settings.compiler.libcxx=${{ matrix.config.lib }} default
|
||||
fi
|
||||
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
|
||||
shell: bash
|
||||
env:
|
||||
|
28
.github/workflows/ci-test-package-cmake.yml
vendored
28
.github/workflows/ci-test-package-cmake.yml
vendored
@@ -84,6 +84,7 @@ jobs:
|
||||
CC: ${{ matrix.config.compiler.cc }}
|
||||
CXX: ${{ matrix.config.compiler.cxx }}
|
||||
CMAKE_GENERATOR: Ninja
|
||||
CONAN_CMAKE_GENERATOR: Ninja
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@@ -143,18 +144,20 @@ jobs:
|
||||
conan profile update settings.compiler.libcxx=${{ matrix.config.lib }} default
|
||||
fi
|
||||
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
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p build/${{ matrix.build_type }} && cd build/${{ matrix.build_type }}
|
||||
conan install ../.. -b outdated -u
|
||||
- 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
|
||||
working-directory: build/${{ matrix.build_type }}
|
||||
run: |
|
||||
@@ -164,16 +167,25 @@ jobs:
|
||||
working-directory: build/${{ matrix.build_type }}
|
||||
run: |
|
||||
cmake --install . --prefix test_package
|
||||
- name: Configure test_package CMake
|
||||
- name: Install dependencies for test_package
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p test_package/build/${{ matrix.build_type }} && cd test_package/build/${{ matrix.build_type }}
|
||||
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
|
||||
- name: Build test_package
|
||||
cmake --build .
|
||||
- name: Build test_package CMake
|
||||
if: matrix.config.compiler.type != 'VISUAL'
|
||||
shell: bash
|
||||
working-directory: test_package/build/${{ matrix.build_type }}
|
||||
run: |
|
||||
cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_INSTALL_PREFIX=../../../build/${{ matrix.build_type }}/test_package
|
||||
cmake --build .
|
||||
- name: Run test_package
|
||||
shell: bash
|
||||
|
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@@ -84,7 +84,7 @@ jobs:
|
||||
pip install -U conan
|
||||
conan config init
|
||||
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
|
||||
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 ..
|
||||
|
3
.github/workflows/documentation.yml
vendored
3
.github/workflows/documentation.yml
vendored
@@ -40,6 +40,7 @@ env:
|
||||
CC: gcc-10
|
||||
CXX: g++-10
|
||||
CMAKE_GENERATOR: Ninja
|
||||
CONAN_CMAKE_GENERATOR: Ninja
|
||||
|
||||
jobs:
|
||||
docs:
|
||||
@@ -75,7 +76,7 @@ jobs:
|
||||
run: |
|
||||
conan config init
|
||||
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
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -38,6 +38,7 @@
|
||||
/cmake-build-*/
|
||||
/build/
|
||||
/out/
|
||||
_build/
|
||||
|
||||
# Conan
|
||||
*.pyc
|
||||
|
@@ -27,6 +27,14 @@ project(mp-units-dev
|
||||
|
||||
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
|
||||
include(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)
|
||||
if(UNITS_IWYU)
|
||||
include(include-what-you-use)
|
||||
set_iwyu(
|
||||
enable_iwyu(
|
||||
MAPPING_FILE "${PROJECT_SOURCE_DIR}/.mp-units.imp"
|
||||
NO_FORWARD_DECLARATIONS
|
||||
QUOTED_INCLUDES_FIRST
|
||||
|
14
README.md
14
README.md
@@ -2,8 +2,8 @@
|
||||
[](https://github.com/mpusz/units/actions?query=workflow%3A%22Conan%20CI%22+branch%3Amaster)
|
||||
[](https://github.com/mpusz/units/actions?query=workflow%3A%22CMake+Test+Package+CI%22+branch%3Amaster)
|
||||
[](https://github.com/mpusz/units/actions?query=workflow%3ADocumentation+branch%3Amaster)
|
||||
[](https://conan.io/center/mp-units)
|
||||
[](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units/0.7.0)
|
||||
[](https://conan.io/center/mp-units)
|
||||
[](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units/0.8.0)
|
||||
|
||||
# `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:
|
||||
|
||||
```cpp
|
||||
#define UNITS_REFERENCES
|
||||
|
||||
#include <units/isq/si/area.h>
|
||||
#include <units/isq/si/frequency.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);
|
||||
```
|
||||
|
||||
_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
|
||||
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:
|
||||
|
||||
```cpp
|
||||
#define UNITS_ALIASES
|
||||
#define UNITS_LITERALS
|
||||
#define UNITS_REFERENCES
|
||||
|
||||
#include <units/format.h>
|
||||
#include <units/isq/si/international/length.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)._
|
||||
|
2
build.py
2
build.py
@@ -36,7 +36,7 @@ if __name__ == "__main__":
|
||||
|
||||
# dependencies
|
||||
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"],
|
||||
upload_dependencies = "all",
|
||||
|
221
cmake/ccache.cmake
Normal file
221
cmake/ccache.cmake
Normal 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()
|
@@ -49,7 +49,7 @@ function(add_documentation targetName)
|
||||
if(NOT _args_DOXYFILE_TEMPLATE)
|
||||
set(_args_DOXYFILE_TEMPLATE Doxyfile.in)
|
||||
endif()
|
||||
file(REAL_PATH ${_args_DOXYFILE_TEMPLATE} _doxyfileIn)
|
||||
get_filename_component(_doxyfileIn ${_args_DOXYFILE_TEMPLATE} REALPATH)
|
||||
if(NOT EXISTS ${_doxyfileIn})
|
||||
message(FATAL_ERROR "'${_args_DOXYFILE_TEMPLATE}' does not exist")
|
||||
endif()
|
||||
|
@@ -30,53 +30,82 @@ endif()
|
||||
|
||||
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)
|
||||
list(APPEND _iwyu_args "-Xiwyu" "${arg}")
|
||||
endmacro()
|
||||
|
||||
macro(_iwyu_args_append_if_present option arg)
|
||||
if(_set_iwyu_${option})
|
||||
if(_enable_iwyu_${option})
|
||||
_iwyu_args_append("${arg}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(_process_iwyu_arguments offset)
|
||||
set(_options NO_DEFAULT_MAPPINGS PCH_IN_CODE TRANSITIVE_INCLUDES_ONLY NO_COMMENTS NO_FORWARD_DECLARATIONS CXX17_NAMESPACES QUOTED_INCLUDES_FIRST)
|
||||
set(_one_value_args MAPPING_FILE MAX_LINE_LENGTH)
|
||||
macro(_enable_iwyu_failed log_postfix)
|
||||
if(NOT _enable_iwyu_QUIET)
|
||||
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)
|
||||
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
|
||||
if(${prefix}_UNPARSED_ARGUMENTS)
|
||||
message(FATAL_ERROR "Invalid arguments '${${prefix}_UNPARSED_ARGUMENTS}'")
|
||||
if(_enable_iwyu_UNPARSED_ARGUMENTS)
|
||||
message(FATAL_ERROR "Invalid arguments '${_enable_iwyu_UNPARSED_ARGUMENTS}'")
|
||||
endif()
|
||||
|
||||
if(_set_iwyu_KEEP)
|
||||
foreach(_pattern ${_set_iwyu_KEEP})
|
||||
if(_enable_iwyu_KEYWORDS_MISSING_VALUES)
|
||||
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}")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(_set_iwyu_MAPPING_FILE)
|
||||
if(NOT EXISTS ${_set_iwyu_MAPPING_FILE})
|
||||
message(FATAL_ERROR "IWYU: Mapping file '${_set_iwyu_MAPPING_FILE}' does not exist")
|
||||
if(_enable_iwyu_MAPPING_FILE)
|
||||
if(NOT EXISTS ${_enable_iwyu_MAPPING_FILE})
|
||||
message(FATAL_ERROR "IWYU: Mapping file '${_enable_iwyu_MAPPING_FILE}' does not exist")
|
||||
endif()
|
||||
_iwyu_args_append("--mapping_file=${_set_iwyu_MAPPING_FILE}")
|
||||
_iwyu_args_append("--mapping_file=${_enable_iwyu_MAPPING_FILE}")
|
||||
endif()
|
||||
|
||||
if(_set_iwyu_MAX_LINE_LENGTH)
|
||||
if(NOT _set_iwyu_MAX_LINE_LENGTH GREATER 0)
|
||||
message(FATAL_ERROR "IWYU: Invalid MAX_LINE_LENGTH value = '${_set_iwyu_MAX_LINE_LENGTH}")
|
||||
if(_enable_iwyu_MAX_LINE_LENGTH)
|
||||
if(NOT _enable_iwyu_MAX_LINE_LENGTH GREATER 0)
|
||||
message(FATAL_ERROR "IWYU: Invalid MAX_LINE_LENGTH value = '${_enable_iwyu_MAX_LINE_LENGTH}")
|
||||
endif()
|
||||
_iwyu_args_append("--max_line_length=${_set_iwyu_MAX_LINE_LENGTH}")
|
||||
_iwyu_args_append("--max_line_length=${_enable_iwyu_MAX_LINE_LENGTH}")
|
||||
endif()
|
||||
|
||||
_iwyu_args_append_if_present(NO_DEFAULT_MAPPINGS "--no_default_mappings")
|
||||
@@ -88,55 +117,50 @@ macro(_process_iwyu_arguments offset)
|
||||
_iwyu_args_append_if_present(QUOTED_INCLUDES_FIRST "--quoted_includes_first")
|
||||
|
||||
_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()
|
||||
|
||||
#
|
||||
# set_target_iwyu(TargetName
|
||||
# [KEEP pattern...]
|
||||
# [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])
|
||||
# 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(set_target_iwyu target)
|
||||
_find_iwyu()
|
||||
_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")
|
||||
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...]
|
||||
# [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_target_iwyu target)
|
||||
_process_iwyu_arguments(1 " for '${target}'")
|
||||
set_target_properties(${target} PROPERTIES
|
||||
CXX_INCLUDE_WHAT_YOU_USE "${_iwyu_path};${_iwyu_args}"
|
||||
)
|
||||
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()
|
||||
|
31
cmake/modern_project_structure.cmake
Normal file
31
cmake/modern_project_structure.cmake
Normal 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()
|
@@ -22,7 +22,7 @@
|
||||
|
||||
# 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)
|
||||
|
||||
@@ -90,8 +90,6 @@ macro(_set_flags)
|
||||
endif()
|
||||
|
||||
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})
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
|
||||
set(flags ${CLANG_WARNINGS})
|
||||
|
47
conanfile.py
47
conanfile.py
@@ -22,7 +22,7 @@
|
||||
|
||||
from conans import ConanFile, tools
|
||||
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
|
||||
import os, re
|
||||
|
||||
@@ -58,28 +58,27 @@ class UnitsConan(ConanFile):
|
||||
# }
|
||||
generators = "cmake_paths"
|
||||
|
||||
_cmake = None
|
||||
|
||||
@property
|
||||
def _run_tests(self):
|
||||
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):
|
||||
content = tools.load(os.path.join(self.recipe_folder, "src/CMakeLists.txt"))
|
||||
version = re.search(r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content).group(1)
|
||||
self.version = version.strip()
|
||||
|
||||
def requirements(self):
|
||||
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):
|
||||
compiler = self.settings.compiler
|
||||
version = Version(self.settings.compiler.version)
|
||||
@@ -102,20 +101,8 @@ class UnitsConan(ConanFile):
|
||||
# # build_docs has sense only in a development or CI build
|
||||
# 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):
|
||||
tc = CMakeToolchain(self)
|
||||
tc = CMakeToolchain(self, generator=os.getenv("CONAN_CMAKE_GENERATOR"))
|
||||
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
|
||||
tc.variables["UNITS_BUILD_DOCS"] = self.options.build_docs
|
||||
@@ -124,14 +111,16 @@ class UnitsConan(ConanFile):
|
||||
deps.generate()
|
||||
|
||||
def build(self):
|
||||
cmake = self._configure_cmake()
|
||||
cmake = CMake(self)
|
||||
cmake.configure(source_folder=None if self._run_tests else "src")
|
||||
cmake.build()
|
||||
if self._run_tests:
|
||||
cmake.test(output_on_failure=True)
|
||||
|
||||
def package(self):
|
||||
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()
|
||||
|
||||
def package_id(self):
|
||||
|
@@ -1,12 +1,19 @@
|
||||
# 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: output stream operators moved to the `units/quantity_io.h` header file
|
||||
- (!) refactor: Refactored the library file tree
|
||||
- (!) refactor: `quantity::count()` renamed to `quantity::number()`
|
||||
- (!) 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: basic concepts, `quantity` and `quantity_cast` refactored
|
||||
- refactor: `abs()` definition refactored to be more explicit about the return type
|
||||
@@ -17,12 +24,15 @@
|
||||
- feat: CTAD for dimensionless quantity added
|
||||
- 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: 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: `quantity_cast()` generates less assembly instructions
|
||||
- perf: temporary string creation removed from `quantity::op<<()`
|
||||
- perf: value initialization for quantity value removed (left with a default initialization)
|
||||
- perf: limited the `equivalent` trait 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: `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
|
||||
@@ -30,7 +40,10 @@
|
||||
- fix: ambiguous case for empty type list resolved
|
||||
- fix: downcasting facility for non-default-constructible types
|
||||
- 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: 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: doxygen updated to 1.8.20
|
||||
- build: catch2 updated to 2.13.4
|
||||
@@ -39,6 +52,7 @@
|
||||
- build: Conan generator switched to `cmake_find_package_multi`
|
||||
- build: Conan CMakeToolchain support added
|
||||
- build: CMake scripts cleanup
|
||||
- build: ccache support added
|
||||
- ci: CI switched from Travis CI to GitHub Actions
|
||||
|
||||
- **0.6.0 September 13, 2020**
|
||||
|
@@ -91,15 +91,3 @@ WARN_AS_ERROR = NO
|
||||
# The default value is: NO.
|
||||
|
||||
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
|
||||
|
BIN
docs/_static/img/concepts.png
vendored
BIN
docs/_static/img/concepts.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 165 KiB After Width: | Height: | Size: 134 KiB |
BIN
docs/_static/img/units.png
vendored
BIN
docs/_static/img/units.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 54 KiB |
@@ -1,7 +1,7 @@
|
||||
avg_speed
|
||||
=========
|
||||
|
||||
.. literalinclude:: ../../example/references/avg_speed.cpp
|
||||
.. literalinclude:: ../../../example/references/avg_speed.cpp
|
||||
:caption: avg_speed.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
box_example
|
||||
===========
|
||||
|
||||
.. literalinclude:: ../../example/references/box_example.cpp
|
||||
.. literalinclude:: ../../../example/references/box_example.cpp
|
||||
:caption: box_example.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
capacitor_time_curve
|
||||
====================
|
||||
|
||||
.. literalinclude:: ../../example/references/capacitor_time_curve.cpp
|
||||
.. literalinclude:: ../../../example/references/capacitor_time_curve.cpp
|
||||
:caption: capacitor_time_curve.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
clcpp_response
|
||||
==============
|
||||
|
||||
.. literalinclude:: ../../example/references/clcpp_response.cpp
|
||||
.. literalinclude:: ../../../example/references/clcpp_response.cpp
|
||||
:caption: clcpp_response.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
experimental_angle
|
||||
==================
|
||||
|
||||
.. literalinclude:: ../../example/references/experimental_angle.cpp
|
||||
.. literalinclude:: ../../../example/references/experimental_angle.cpp
|
||||
:caption: experimental_angle.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
foot_pound_second
|
||||
=================
|
||||
|
||||
.. literalinclude:: ../../example/references/foot_pound_second.cpp
|
||||
.. literalinclude:: ../../../example/references/foot_pound_second.cpp
|
||||
:caption: foot_pound_second.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
||||
|
@@ -13,7 +13,7 @@ This example presents the usage of:
|
||||
- quantities text output formatting,
|
||||
- cooperation with `std::chrono`.
|
||||
|
||||
.. literalinclude:: ../../example/glide_computer/include/glide_computer.h
|
||||
.. literalinclude:: ../../../example/glide_computer/include/glide_computer.h
|
||||
:caption: glide_computer.h
|
||||
:start-at: #include
|
||||
: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
|
||||
- ``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
|
||||
:start-at: using namespace units;
|
||||
: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.
|
||||
|
||||
.. literalinclude:: ../../example/glide_computer/include/glide_computer.h
|
||||
.. literalinclude:: ../../../example/glide_computer/include/glide_computer.h
|
||||
:caption: glide_computer.h
|
||||
:start-at: // text output
|
||||
: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,
|
||||
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
|
||||
:start-at: // definition of glide computer databases and utilities
|
||||
:linenos:
|
||||
:lineno-match:
|
||||
|
||||
.. literalinclude:: ../../example/references/glide_computer_example.cpp
|
||||
.. literalinclude:: ../../../example/references/glide_computer_example.cpp
|
||||
:caption: glide_computer_example.cpp
|
||||
:start-at: #include
|
||||
: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
|
||||
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
|
||||
:start-at: #include
|
||||
:linenos:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
hello_units
|
||||
===========
|
||||
|
||||
.. literalinclude:: ../../example/hello_units.cpp
|
||||
.. literalinclude:: ../../../example/hello_units.cpp
|
||||
:caption: hello_units.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
total_energy
|
||||
============
|
||||
|
||||
.. literalinclude:: ../../example/references/total_energy.cpp
|
||||
.. literalinclude:: ../../../example/references/total_energy.cpp
|
||||
:caption: total_energy.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
unknown_dimension
|
||||
=================
|
||||
|
||||
.. literalinclude:: ../../example/references/unknown_dimension.cpp
|
||||
.. literalinclude:: ../../../example/references/unknown_dimension.cpp
|
||||
:caption: unknown_dimension.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
linear_algebra
|
||||
==============
|
||||
|
||||
.. literalinclude:: ../../example/references/linear_algebra.cpp
|
||||
.. literalinclude:: ../../../example/references/linear_algebra.cpp
|
||||
:caption: linear_algebra.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
measurement
|
||||
===========
|
||||
|
||||
.. literalinclude:: ../../example/measurement.cpp
|
||||
.. literalinclude:: ../../../example/measurement.cpp
|
||||
:caption: measurement.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
custom_systems
|
||||
==============
|
||||
|
||||
.. literalinclude:: ../../example/custom_systems.cpp
|
||||
.. literalinclude:: ../../../example/custom_systems.cpp
|
||||
:caption: custom_systems.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
conversion_factor
|
||||
=================
|
||||
|
||||
.. literalinclude:: ../../example/conversion_factor.cpp
|
||||
.. literalinclude:: ../../../example/conversion_factor.cpp
|
||||
:caption: conversion_factor.cpp
|
||||
:start-at: #include
|
||||
:linenos:
|
||||
|
@@ -23,7 +23,7 @@ The most important concepts in the library are `Unit`, `Dimension`,
|
||||
]
|
||||
|
||||
[<abstract>QuantityPoint|
|
||||
[quantity_point<Dimension, Unit, Rep>]
|
||||
[quantity_point<PointOrigin, Unit, Rep>]
|
||||
]
|
||||
|
||||
[<abstract>QuantityKind|
|
||||
@@ -39,6 +39,10 @@ The most important concepts in the library are `Unit`, `Dimension`,
|
||||
[Unit]<-[Quantity]
|
||||
[Quantity]<-[QuantityPoint]
|
||||
|
||||
[<abstract>PointOrigin]<-[QuantityPoint]
|
||||
[Dimension]<-[PointOrigin]
|
||||
[PointOrigin]<-[PointKind]
|
||||
|
||||
[<abstract>Kind]<-[QuantityKind]
|
||||
[Dimension]<-[Kind]
|
||||
[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>``,
|
||||
``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
|
||||
(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
|
||||
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
|
||||
height).
|
||||
|
@@ -77,7 +77,7 @@ you can use a quantity argument instead of a quantity kind.
|
||||
:emphasize-lines: 8-9
|
||||
|
||||
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 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
|
||||
|
||||
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 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 can be added to or subtracted from a quantity point.
|
||||
The result will always be a quantity point of the same dimension:
|
||||
Quantity can be added to or subtracted
|
||||
from a quantity point of the same origin.
|
||||
The result will always be a quantity point of the same origin:
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 3-5
|
||||
@@ -132,9 +133,10 @@ The result is a relative quantity of the same dimension:
|
||||
|
||||
It is not allowed to:
|
||||
|
||||
- add quantity points
|
||||
- subtract a quantity point from a quantity:
|
||||
- multiply nor divide quantity points with anything else.
|
||||
- add quantity points,
|
||||
- subtract a quantity point from a quantity,
|
||||
- multiply nor divide quantity points with anything else, and
|
||||
- mix quantity points with different origins:
|
||||
|
||||
.. code-block::
|
||||
: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 res2 = dist1 - quantity_point{dist2}; // 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
|
||||
++++++++++++++++++++
|
||||
|
@@ -70,7 +70,7 @@ Unit-Specific Aliases (Experimental)
|
||||
Additionally to the dimension-specific aliases there are also ones provided for
|
||||
each and every :term:`unit` in the library::
|
||||
|
||||
#ifdef UNITS_ALIASES
|
||||
#ifndef UNITS_NO_ALIASES
|
||||
|
||||
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::
|
||||
|
||||
@@ -116,7 +116,7 @@ Quantity References (Experimental)
|
||||
Quantity References provide an alternative and simplified way to create quantities.
|
||||
They are defined using the `reference` class template::
|
||||
|
||||
#ifdef UNITS_REFERENCES
|
||||
#ifndef UNITS_NO_REFERENCES
|
||||
|
||||
namespace length_references {
|
||||
|
||||
@@ -131,7 +131,7 @@ They are defined using the `reference` class template::
|
||||
|
||||
} // namespace references
|
||||
|
||||
#endif // UNITS_REFERENCES
|
||||
#endif // UNITS_NO_REFERENCES
|
||||
|
||||
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
|
||||
:abbr:`UDL (User Defined Literal)` s for each :term:`unit` of every :term:`dimension`::
|
||||
|
||||
#ifdef UNITS_LITERALS
|
||||
#ifndef UNITS_NO_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::
|
||||
|
||||
@@ -185,13 +185,6 @@ Thanks to them the same code can be as simple as::
|
||||
language (i.e. ``F`` (farad), ``J`` (joule), ``W`` (watt), ``K`` (kelvin),
|
||||
``d`` (day), ``l`` or ``L`` (litre), ``erg``, ``ergps``). This is why the
|
||||
``_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
|
||||
+++++++++++++++++++++++++++
|
||||
@@ -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
|
||||
---------------------------
|
||||
|
||||
|
@@ -3,9 +3,20 @@
|
||||
Quantity Points
|
||||
===============
|
||||
|
||||
A quantity point is an absolute quantity with respect to zero
|
||||
(which represents some origin) and is represented in the library with a
|
||||
`quantity_point` class template.
|
||||
A quantity point is an absolute quantity with respect to an origin
|
||||
and is represented in the library with a `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
|
||||
@@ -14,7 +25,7 @@ Construction
|
||||
To create the quantity point object from a `quantity` we just have to pass
|
||||
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::
|
||||
|
||||
@@ -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>`_
|
||||
**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
|
||||
|
@@ -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
|
||||
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
|
||||
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>`
|
||||
(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.
|
||||
|
||||
|
||||
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), ``m²``
|
||||
(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
|
||||
------------
|
||||
|
||||
Until now we talked mostly about
|
||||
:term:`coherent units <coherent derived unit>` which are units used to
|
||||
define dimensions and thus, in their system of units, have proportionality
|
||||
factor/ratio equals one. However quantities of each dimension can also use
|
||||
other units of measurement to describe their magnitude (numerical value).
|
||||
Described above base units (in case of base quantities) and
|
||||
:term:`coherent units <coherent derived unit>` (in case of derived quantities),
|
||||
in their system of units, have proportionality factor/ratio equal to one.
|
||||
However, quantities of such dimensions can also use units of measurement
|
||||
with other ratios to describe their magnitude (numerical value).
|
||||
|
||||
|
||||
Named Scaled Units
|
||||
@@ -289,13 +206,99 @@ example we can define ``si::kilometre`` as::
|
||||
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), ``m²``
|
||||
(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,
|
||||
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
|
||||
ratio in reference to "metre per second":
|
||||
ratio in reference to the "metre per second":
|
||||
|
||||
- ``1000/3600``
|
||||
- ``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.
|
||||
|
||||
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::
|
||||
|
||||
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
|
||||
`named_deduced_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
|
||||
based on the ingredients::
|
||||
In case the scaled derived unit should serve as a named one we can use
|
||||
a `named_derived_unit` where the user is able to provide a symbol for the unit
|
||||
by him/her-self::
|
||||
|
||||
namespace si::fps {
|
||||
|
||||
struct nautical_mile_per_hour : named_deduced_unit<nautical_mile_per_hour, dim_speed,
|
||||
"knot", no_prefix, nautical_mile, hour>{};
|
||||
struct foot_pound_force : noble_deduced_unit<foot_pound_force, dim_energy, pound_force, foot> {};
|
||||
struct knot : named_derived_unit<knot, dim_speed, "knot", no_prefix, nautical_mile, hour> {};
|
||||
|
||||
}
|
||||
|
||||
Please note that deduced units are the only unit-related class template that
|
||||
take a dimension as its parameter. This derived dimension provides a :term:`recipe`
|
||||
Please note that the dervided scaled units are the only unit-related class templates
|
||||
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
|
||||
(order, type, and exponents of composite dimensions) and the ratios of units
|
||||
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_scaled_unit<Child, Symbol, PrefixFamily, Ratio, Unit>]
|
||||
[scaled_unit<UnitRatio, Unit>]<:-[prefixed_unit<Child, Prefix, Unit>]
|
||||
[scaled_unit<UnitRatio, Unit>]<:-[deduced_unit<Child, Dimension, Unit, Unit...>]
|
||||
[scaled_unit<UnitRatio, Unit>]<:-[noble_deduced_unit<Child, Dimension, Unit, Unit...>]
|
||||
[scaled_unit<UnitRatio, Unit>]<:-[named_deduced_unit<Child, Dimension, Symbol, PrefixFamily, Unit, Unit...>]
|
||||
[scaled_unit<UnitRatio, Unit>]<:-[derived_unit<Child, Dimension, Unit, Unit...>]
|
||||
[scaled_unit<UnitRatio, Unit>]<:-[named_derived_unit<Child, Dimension, Symbol, PrefixFamily, Unit, Unit...>]
|
||||
[scaled_unit<UnitRatio, Unit>]<:-[alias_unit<Unit, Symbol, PrefixFamily>]
|
||||
[scaled_unit<UnitRatio, Unit>]<:-[prefixed_alias_unit<Unit, Prefix, AliasUnit>]
|
||||
|
||||
|
@@ -3,8 +3,6 @@ Quick Start
|
||||
|
||||
Here is a small example of possible operations::
|
||||
|
||||
#define UNITS_REFERENCES
|
||||
|
||||
#include <units/isq/si/area.h>
|
||||
#include <units/isq/si/frequency.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
|
||||
|
||||
`Example #1 <https://godbolt.org/z/53bTahKd8>`_
|
||||
`Example #1 <https://godbolt.org/z/5dvY8Woh1>`_
|
||||
|
||||
This library requires some C++20 features (concepts, classes as
|
||||
: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
|
||||
of basic library features::
|
||||
|
||||
#define UNITS_ALIASES
|
||||
#define UNITS_LITERALS
|
||||
#define UNITS_REFERENCES
|
||||
|
||||
#include <units/format.h>
|
||||
#include <units/isq/si/international/length.h>
|
||||
#include <units/isq/si/international/speed.h>
|
||||
@@ -92,7 +86,7 @@ of basic library features::
|
||||
|
||||
.. admonition:: Try it on Compiler Explorer
|
||||
|
||||
`Example #2 <https://godbolt.org/z/jKnPPPEx6>`_
|
||||
`Example #2 <https://godbolt.org/z/9fnzfbhb6>`_
|
||||
|
||||
.. seealso::
|
||||
|
||||
|
@@ -16,13 +16,10 @@ Units
|
||||
.. doxygenstruct:: units::prefixed_unit
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::deduced_unit
|
||||
.. doxygenstruct:: units::derived_unit
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::noble_deduced_unit
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::named_deduced_unit
|
||||
.. doxygenstruct:: units::named_derived_unit
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: units::alias_unit
|
||||
|
@@ -92,7 +92,6 @@ in *~/.conan/profiles* directory. An example profile can look as follows:
|
||||
[env]
|
||||
CC=/usr/bin/gcc-10
|
||||
CXX=/usr/bin/g++-10
|
||||
CONAN_CMAKE_GENERATOR=Ninja
|
||||
|
||||
.. tip::
|
||||
|
||||
@@ -248,7 +247,7 @@ library release the following steps may be performed:
|
||||
:caption: conanfile.txt
|
||||
|
||||
[requires]
|
||||
mp-units/0.6.0
|
||||
mp-units/0.7.0
|
||||
|
||||
[generators]
|
||||
CMakeToolchain
|
||||
@@ -279,7 +278,7 @@ library release the following steps may be performed:
|
||||
|
||||
.. 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
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
|
||||
cmake --build .
|
||||
@@ -314,7 +313,7 @@ differences:
|
||||
:caption: conanfile.txt
|
||||
|
||||
[requires]
|
||||
mp-units/0.7.0@mpusz/testing
|
||||
mp-units/0.8.0@mpusz/testing
|
||||
|
||||
[generators]
|
||||
CMakeToolchain
|
||||
@@ -330,12 +329,27 @@ differences:
|
||||
|
||||
.. 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
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
|
||||
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)
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
@@ -349,10 +363,10 @@ in **mp-units** repository, you should:
|
||||
|
||||
.. 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
|
||||
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 build ..
|
||||
|
||||
@@ -387,4 +401,4 @@ Uploading **mp-units** Package to the Conan Server
|
||||
|
||||
.. 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>
|
||||
|
@@ -118,7 +118,7 @@ coherent unit::
|
||||
exponent<si::dim_area, 1>, exponent<si::dim_time, -1>> {};
|
||||
|
||||
// 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
|
||||
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<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>
|
||||
using occupancy_rate = quantity<dim_occupancy_rate, U, Rep>;
|
||||
|
@@ -56,11 +56,12 @@ such an explicit conversion::
|
||||
|
||||
For external quantity point-like types, `quantity_point_like_traits` is also provided.
|
||||
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`
|
||||
provide a deduction guide from `QuantityPointLike`::
|
||||
|
||||
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);
|
||||
|
@@ -11,7 +11,7 @@ enough to be used with other Linear Algebra libraries existing on the market.
|
||||
All of the examples provided in this chapter refer to the official proposal of the
|
||||
Linear Algebra Library for the C++23 defined in `P1385 <https://wg21.link/P1385>`_
|
||||
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::
|
||||
|
||||
using namespace std::math;
|
||||
|
@@ -28,7 +28,10 @@ cmake_minimum_required(VERSION 3.2)
|
||||
function(add_example target)
|
||||
add_executable(${target}-aliases ${target}.cpp)
|
||||
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()
|
||||
|
||||
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)
|
||||
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)
|
||||
add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si)
|
||||
|
@@ -53,8 +53,8 @@ distance spherical_distance(position from, position to)
|
||||
return distance(earth_radius * central_angle);
|
||||
} else {
|
||||
// the haversine formula
|
||||
const auto sin_lat = sin(lat2 - lat1) / 2;
|
||||
const auto sin_lon = sin(lon2 - lon1) / 2;
|
||||
const auto sin_lat = sin((lat2 - lat1) / 2);
|
||||
const auto sin_lon = sin((lon2 - lon1) / 2);
|
||||
const auto central_angle = 2 * asin(sqrt(sin_lat * sin_lat + cos(lat1) * cos(lat2) * sin_lon * sin_lon));
|
||||
return distance(earth_radius * central_angle);
|
||||
}
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include <units/quantity_point_kind.h>
|
||||
// IWYU pragma: end_exports
|
||||
|
||||
#include <units/chrono.h>
|
||||
#include <units/format.h>
|
||||
#include <units/math.h> // IWYU pragma: keep
|
||||
#include <algorithm>
|
||||
@@ -77,8 +78,8 @@ constexpr units::Dimensionless auto operator/(const QK1& lhs, const QK2& rhs)
|
||||
using horizontal_kind = geographic::horizontal_kind;
|
||||
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 velocity_kind : units::derived_kind<velocity_kind, horizontal_kind, units::isq::si::dim_speed> {};
|
||||
struct rate_of_climb_kind : units::derived_kind<rate_of_climb_kind, vertical_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, units::isq::si::dim_speed, vertical_kind> {};
|
||||
|
||||
// https://en.wikipedia.org/wiki/Flight_planning#Units_of_measurement
|
||||
// length
|
||||
@@ -88,7 +89,7 @@ using altitude = units::quantity_point_kind<vertical_point_kind, units::isq::si:
|
||||
|
||||
// time
|
||||
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
|
||||
using velocity = units::quantity_kind<velocity_kind, units::isq::si::kilometre_per_hour>;
|
||||
|
@@ -20,10 +20,6 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#define UNITS_ALIASES
|
||||
#define UNITS_LITERALS
|
||||
#define UNITS_REFERENCES
|
||||
|
||||
#include <units/format.h>
|
||||
#include <units/isq/si/international/length.h>
|
||||
#include <units/isq/si/international/speed.h> // IWYU pragma: keep
|
||||
|
@@ -28,7 +28,10 @@ cmake_minimum_required(VERSION 3.2)
|
||||
function(add_example target)
|
||||
add_executable(${target} ${target}.cpp)
|
||||
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()
|
||||
|
||||
add_example(kalman_filter-example_1 mp-units::core-fmt mp-units::si)
|
||||
|
@@ -28,7 +28,10 @@ cmake_minimum_required(VERSION 3.2)
|
||||
function(add_example target)
|
||||
add_executable(${target}-literals ${target}.cpp)
|
||||
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()
|
||||
|
||||
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)
|
||||
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)
|
||||
add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si)
|
||||
|
@@ -28,7 +28,10 @@ cmake_minimum_required(VERSION 3.2)
|
||||
function(add_example target)
|
||||
add_executable(${target}-references ${target}.cpp)
|
||||
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()
|
||||
|
||||
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)
|
||||
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)
|
||||
add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si)
|
||||
|
@@ -22,7 +22,7 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(mp-units
|
||||
VERSION 0.7.0
|
||||
VERSION 0.8.0
|
||||
LANGUAGES CXX
|
||||
)
|
||||
|
||||
|
@@ -205,6 +205,52 @@ concept UnitOf =
|
||||
Dimension<D> &&
|
||||
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
|
||||
namespace detail {
|
||||
|
||||
@@ -216,7 +262,7 @@ struct _kind_base;
|
||||
template<typename T, template<typename...> typename Base>
|
||||
concept kind_impl_ =
|
||||
is_derived_from_specialization_of<T, Base> &&
|
||||
requires(T* t) {
|
||||
requires {
|
||||
typename T::base_kind;
|
||||
typename T::dimension;
|
||||
requires Dimension<typename T::dimension>;
|
||||
@@ -236,7 +282,7 @@ concept Kind =
|
||||
// PointKind
|
||||
namespace detail {
|
||||
|
||||
template<Kind>
|
||||
template<Kind, PointOrigin>
|
||||
struct _point_kind_base;
|
||||
|
||||
} // namespace detail
|
||||
@@ -247,7 +293,12 @@ struct _point_kind_base;
|
||||
* Satisfied by all point kind types derived from an specialization of @c point_kind.
|
||||
*/
|
||||
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
|
||||
namespace detail {
|
||||
|
@@ -31,7 +31,7 @@ namespace units {
|
||||
template<Dimension D, UnitOf<D> U, Representation Rep>
|
||||
class quantity;
|
||||
|
||||
template<Dimension D, UnitOf<D> U, Representation Rep>
|
||||
template<PointOrigin O, UnitOf<typename O::dimension> U, Representation Rep>
|
||||
class quantity_point;
|
||||
|
||||
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>; }
|
||||
struct common_type<QP1, QP2> {
|
||||
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>::rep>;
|
||||
};
|
||||
|
@@ -80,16 +80,16 @@ template<typename... Es>
|
||||
inline constexpr int negative_exp_count = ((Es::num < 0 ? 1 : 0) + ... + 0);
|
||||
|
||||
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...>;
|
||||
return (exp_text<Es, Us::symbol, neg_exp, Idxs>() + ...);
|
||||
}
|
||||
|
||||
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
|
@@ -33,7 +33,7 @@ inline constexpr bool same_scaled_units = false;
|
||||
template<typename... Es, Unit... Us>
|
||||
inline constexpr bool same_scaled_units<exponent_list<Es...>, Us...> = (UnitOf<Us, typename Es::dimension> && ...);
|
||||
|
||||
// deduced_unit
|
||||
// derived_unit
|
||||
|
||||
template<Exponent E>
|
||||
constexpr ratio inverse_if_negative(const ratio& r)
|
||||
@@ -51,6 +51,6 @@ constexpr ratio derived_ratio(exponent_list<Es...>)
|
||||
}
|
||||
|
||||
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
|
@@ -81,29 +81,51 @@ template<Unit U1, Dimension D1, Unit U2, Dimension D2>
|
||||
struct equivalent_unit : std::disjunction<equivalent_impl<U1, U2>,
|
||||
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
|
||||
|
||||
template<typename T, typename U>
|
||||
requires (Kind<T> && Kind<U>) || (PointKind<T> && PointKind<U>)
|
||||
template<Kind T, Kind U>
|
||||
struct equivalent_impl<T, U> :
|
||||
std::conjunction<std::is_same<typename T::base_kind, typename U::base_kind>,
|
||||
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
|
||||
|
||||
template<typename Q1, typename Q2>
|
||||
requires (Quantity<Q1> && Quantity<Q2>) || (QuantityPoint<Q1> && QuantityPoint<Q2>)
|
||||
template<Quantity Q1, Quantity Q2>
|
||||
struct equivalent_impl<Q1, Q2> : std::conjunction<equivalent_impl<typename Q1::dimension, typename Q2::dimension>,
|
||||
equivalent_unit<typename Q1::unit, typename Q1::dimension,
|
||||
typename Q2::unit, typename Q2::dimension>> {};
|
||||
|
||||
template<typename QK1, typename QK2>
|
||||
requires (QuantityKind<QK1> && QuantityKind<QK2>) || (QuantityPointKind<QK1> && QuantityPointKind<QK2>)
|
||||
template<QuantityPoint QP1, QuantityPoint QP2>
|
||||
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>,
|
||||
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
|
||||
|
||||
template<typename T, typename U>
|
||||
|
@@ -85,21 +85,20 @@ template<typename Q1, typename Q2>
|
||||
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
|
||||
* the provided dimension type.
|
||||
* Satisfied by all quantity points with an origin equivalent to the provided one.
|
||||
*/
|
||||
template<typename QP, typename Dim>
|
||||
concept QuantityPointOf = QuantityPoint<QP> && Dimension<Dim> && equivalent<typename QP::dimension, Dim>;
|
||||
template<typename QP, typename Orig>
|
||||
concept QuantityPointOf = QuantityPoint<QP> && PointOrigin<Orig> && equivalent<typename QP::origin, Orig>;
|
||||
|
||||
/**
|
||||
* @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>
|
||||
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.
|
||||
|
@@ -22,7 +22,7 @@
|
||||
|
||||
#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/prefix.h>
|
||||
#include <units/derived_dimension.h>
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include <units/customization_points.h>
|
||||
// IWYU pragma: begin_exports
|
||||
#include <units/isq/si/time.h>
|
||||
#include <units/point_origin.h>
|
||||
#include <chrono>
|
||||
// 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(); }
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
struct clock_origin : point_origin<isq::si::dim_time> { };
|
||||
|
||||
template<typename C, typename Rep, typename Period>
|
||||
struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::duration<Rep, Period>>> {
|
||||
using dimension = isq::si::dim_time;
|
||||
using unit = downcast_unit<dimension, ratio(Period::num, Period::den)>;
|
||||
using origin = clock_origin<C>;
|
||||
using unit = downcast_unit<typename origin::dimension, ratio(Period::num, Period::den)>;
|
||||
using rep = Rep;
|
||||
[[nodiscard]] static constexpr auto relative(
|
||||
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
|
||||
|
@@ -88,7 +88,7 @@ struct quantity_like_traits;
|
||||
/**
|
||||
* @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.
|
||||
*
|
||||
* Usage example can be found in @c units/chrono.h header file.
|
||||
|
@@ -43,7 +43,7 @@ concept Angle = QuantityOfT<T, dim_angle>;
|
||||
template<UnitOf<dim_angle<>> U, Representation Rep = double>
|
||||
using angle = quantity<dim_angle<>, U, Rep>;
|
||||
|
||||
#ifdef UNITS_LITERALS
|
||||
#ifndef UNITS_NO_LITERALS
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -53,9 +53,9 @@ constexpr auto operator"" _q_rad(long double l) { return angle<radian, long doub
|
||||
|
||||
} // namespace literals
|
||||
|
||||
#endif // UNITS_LITERALS
|
||||
#endif // UNITS_NO_LITERALS
|
||||
|
||||
#ifdef UNITS_REFERENCES
|
||||
#ifndef UNITS_NO_REFERENCES
|
||||
|
||||
namespace angle_references {
|
||||
|
||||
@@ -69,6 +69,6 @@ using namespace angle_references;
|
||||
|
||||
} // namespace references
|
||||
|
||||
#endif // UNITS_REFERENCES
|
||||
#endif // UNITS_NO_REFERENCES
|
||||
|
||||
} // namespace units
|
||||
|
@@ -27,6 +27,9 @@
|
||||
|
||||
namespace units {
|
||||
|
||||
template<Dimension D>
|
||||
struct dynamic_origin;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename K, Dimension D>
|
||||
@@ -35,10 +38,11 @@ struct _kind_base : downcast_base<_kind_base<K, D>> {
|
||||
using dimension = D;
|
||||
};
|
||||
|
||||
template<Kind K>
|
||||
struct _point_kind_base : downcast_base<_point_kind_base<K>> {
|
||||
template<Kind K, PointOrigin O>
|
||||
struct _point_kind_base : downcast_base<_point_kind_base<K, O>> {
|
||||
using base_kind = K;
|
||||
using dimension = typename K::dimension;
|
||||
using origin = O;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
@@ -47,18 +51,18 @@ template<Kind K, Dimension D>
|
||||
requires 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>
|
||||
requires PointKind<downcast<detail::_point_kind_base<K>>>
|
||||
using downcast_point_kind = downcast<detail::_point_kind_base<K>>;
|
||||
template<Kind K, PointOrigin O = dynamic_origin<typename K::dimension>>
|
||||
requires PointKind<downcast<detail::_point_kind_base<K, O>>>
|
||||
using downcast_point_kind = downcast<detail::_point_kind_base<K, O>>;
|
||||
|
||||
template<typename K, Dimension 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>
|
||||
struct derived_kind : downcast_dispatch<DK, detail::_kind_base<BK, D>> {};
|
||||
|
||||
template<typename DPK, Kind BK>
|
||||
struct point_kind : downcast_dispatch<DPK, detail::_point_kind_base<BK>> {};
|
||||
template<typename DPK, Kind BK, PointOrigin O = dynamic_origin<typename BK::dimension>>
|
||||
struct point_kind : downcast_dispatch<DPK, detail::_point_kind_base<BK, O>> {};
|
||||
|
||||
} // namespace units
|
||||
|
34
src/core/include/units/point_origin.h
Normal file
34
src/core/include/units/point_origin.h
Normal 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
|
@@ -147,9 +147,10 @@ public:
|
||||
quantity(const quantity&) = default;
|
||||
quantity(quantity&&) = default;
|
||||
|
||||
template<safe_convertible_to_<rep> Value>
|
||||
constexpr explicit(!(is_same_v<dimension, dim_one> && is_same_v<unit, ::units::one>))
|
||||
quantity(const Value& v) : number_(v) {}
|
||||
template<typename Value>
|
||||
requires safe_convertible_to_<std::remove_cvref_t<Value>, rep>
|
||||
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>
|
||||
constexpr explicit(false) quantity(const Q& q) : number_(quantity_cast<quantity>(q).number()) {}
|
||||
@@ -162,7 +163,10 @@ public:
|
||||
quantity& operator=(quantity&&) = default;
|
||||
|
||||
// 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
|
||||
[[nodiscard]] constexpr Quantity auto operator+() const
|
||||
@@ -363,11 +367,12 @@ public:
|
||||
}
|
||||
|
||||
[[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>
|
||||
{
|
||||
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)
|
||||
@@ -422,25 +427,15 @@ template<Quantity Q1, Quantity Q2>
|
||||
return detail::make_quantity<Q1::reference / Q2::reference>(lhs.number() / rhs.number());
|
||||
}
|
||||
|
||||
template<typename D1, typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
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>
|
||||
template<Quantity Q1, Quantity Q2>
|
||||
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>
|
||||
[[nodiscard]] constexpr Quantity auto operator%(const Q1& lhs, const Q2& rhs)
|
||||
{
|
||||
gsl_ExpectsAudit(rhs.number() != quantity_values<typename Q2::rep>::zero());
|
||||
using ret = common_quantity_for<std::modulus<>, Q1, Q2>;
|
||||
return ret(ret(lhs).number() % ret(rhs).number());
|
||||
using ret = quantity<typename Q1::dimension, typename Q1::unit, std::invoke_result_t<std::modulus<>, typename Q1::rep, typename Q2::rep>>;
|
||||
return ret(lhs.number() % rhs.number());
|
||||
}
|
||||
|
||||
template<Quantity Q1, QuantityEquivalentTo<Q1> Q2>
|
||||
|
@@ -39,7 +39,7 @@ namespace units {
|
||||
template<Dimension D, UnitOf<D> U, Representation Rep>
|
||||
class quantity;
|
||||
|
||||
template<Dimension D, UnitOf<D> U, Representation Rep>
|
||||
template<PointOrigin O, UnitOf<typename O::dimension> U, Representation Rep>
|
||||
class quantity_point;
|
||||
|
||||
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
|
||||
*/
|
||||
template<typename CastSpec, typename D, typename U, typename Rep>
|
||||
requires is_specialization_of<CastSpec, quantity_point> ||
|
||||
requires(quantity<D, U, Rep> q) { quantity_cast<CastSpec>(q); }
|
||||
[[nodiscard]] constexpr auto quantity_point_cast(const quantity_point<D, U, Rep>& qp)
|
||||
template<typename CastSpec, typename O, typename U, typename Rep>
|
||||
[[nodiscard]] constexpr auto quantity_point_cast(const quantity_point<O, U, Rep>& qp)
|
||||
requires requires { requires is_specialization_of<CastSpec, quantity_point>;
|
||||
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>)
|
||||
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 ToU a unit type to use for a target quantity
|
||||
*/
|
||||
template<Dimension ToD, Unit ToU, typename D, typename U, typename Rep>
|
||||
requires equivalent<ToD, D> && UnitOf<ToU, ToD>
|
||||
[[nodiscard]] constexpr auto quantity_point_cast(const quantity_point<D, U, Rep>& q)
|
||||
template<Dimension ToD, Unit ToU, typename O, typename U, typename Rep>
|
||||
requires equivalent<ToD, typename O::dimension> && UnitOf<ToU, ToD> && RebindablePointOriginFor<O, ToD>
|
||||
[[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>
|
||||
[[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 { 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 { quantity_kind_cast<CastSpec>(qpk.relative()); } // TODO: Simplify when Clang catches up.
|
||||
{
|
||||
|
@@ -93,22 +93,25 @@ public:
|
||||
quantity_kind(const quantity_kind&) = default;
|
||||
quantity_kind(quantity_kind&&) = default;
|
||||
|
||||
template<safe_convertible_to_<rep> Value>
|
||||
requires is_same_v<dimension, dim_one> && std::is_constructible_v<quantity_type, Value>
|
||||
constexpr explicit quantity_kind(const Value& v) : q_(v) {}
|
||||
|
||||
template<typename Q>
|
||||
requires (Quantity<Q> || QuantityLike<Q>) && std::is_constructible_v<quantity_type, Q>
|
||||
constexpr explicit quantity_kind(const Q& q) : q_{q} {}
|
||||
template<typename T>
|
||||
requires
|
||||
(Quantity<std::remove_cvref_t<T>> ||
|
||||
QuantityLike<std::remove_cvref_t<T>> ||
|
||||
(Dimensionless<quantity_type> && !Quantity<std::remove_cvref_t<T>>)) &&
|
||||
std::constructible_from<quantity_type, T>
|
||||
constexpr explicit quantity_kind(T&& t) : q_(std::forward<T>(t)) {}
|
||||
|
||||
template<QuantityKindEquivalentTo<quantity_kind> QK2>
|
||||
requires std::is_convertible_v<typename QK2::quantity_type, quantity_type>
|
||||
constexpr explicit(false) quantity_kind(const QK2& qk) : q_{qk.common()} {}
|
||||
requires std::convertible_to<typename QK2::quantity_type, quantity_type>
|
||||
constexpr explicit(false) quantity_kind(const QK2& qk) : q_(qk.common()) {}
|
||||
|
||||
quantity_kind& operator=(const 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
|
||||
requires requires { quantity_type::zero(); }
|
||||
@@ -225,22 +228,17 @@ public:
|
||||
q_ %= rhs;
|
||||
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(); }
|
||||
|
||||
template<QuantityKind QK>
|
||||
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(rhs.common().number() != quantity_values<typename QK::rep>::zero());
|
||||
q_ %= rhs.common();
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr quantity_kind& operator%=(const quantity_kind& qk)
|
||||
requires requires(quantity_type q) { q %= qk.common(); }
|
||||
{
|
||||
gsl_ExpectsAudit(qk.common().number() != quantity_values<rep>::zero());
|
||||
q_ %= qk.common();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Hidden Friends
|
||||
// Below friend functions are to be found via argument-dependent lookup only
|
||||
template<Representation Value>
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#pragma once
|
||||
|
||||
// IWYU pragma: begin_exports
|
||||
#include <units/point_origin.h>
|
||||
#include <units/quantity.h>
|
||||
#include <compare>
|
||||
// IWYU pragma: end_exports
|
||||
@@ -34,18 +35,32 @@
|
||||
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)
|
||||
*/
|
||||
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 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 {
|
||||
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 unit = typename quantity_type::unit;
|
||||
using rep = typename quantity_type::rep;
|
||||
@@ -59,29 +74,27 @@ public:
|
||||
quantity_point(const quantity_point&) = default;
|
||||
quantity_point(quantity_point&&) = default;
|
||||
|
||||
template<safe_convertible_to_<rep> Value>
|
||||
requires is_same_v<dimension, dim_one> && std::is_constructible_v<quantity_type, Value>
|
||||
constexpr explicit quantity_point(const Value& v) : q_(v) {}
|
||||
template<typename T>
|
||||
requires std::constructible_from<quantity_type, T>
|
||||
constexpr explicit quantity_point(T&& t) : q_(std::forward<T>(t)) {}
|
||||
|
||||
constexpr explicit quantity_point(const quantity_type& q) : q_{q} {}
|
||||
|
||||
template<QuantityLike Q>
|
||||
requires std::is_constructible_v<quantity_type, Q>
|
||||
constexpr explicit quantity_point(const Q& q) : q_{q} {}
|
||||
template<QuantityPointOf<origin> QP2>
|
||||
requires std::convertible_to<typename QP2::quantity_type, quantity_type>
|
||||
constexpr explicit(false) quantity_point(const QP2& qp) : q_(qp.relative()) {}
|
||||
|
||||
template<QuantityPointLike QP>
|
||||
constexpr explicit quantity_point(const QP& qp)
|
||||
requires std::is_constructible_v<quantity_type, decltype(quantity_point_like_traits<QP>::relative(qp))>
|
||||
: 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()} {}
|
||||
requires std::is_constructible_v<quantity_type, decltype(quantity_point_like_traits<QP>::relative(qp))> &&
|
||||
equivalent<origin, typename quantity_point_like_traits<QP>::origin>
|
||||
: q_(quantity_point_like_traits<QP>::relative(qp)) {}
|
||||
|
||||
quantity_point& operator=(const 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
|
||||
requires requires { quantity_type::min(); }
|
||||
@@ -144,7 +157,8 @@ public:
|
||||
{
|
||||
const auto q = lhs.relative() + rhs;
|
||||
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>
|
||||
@@ -160,48 +174,51 @@ public:
|
||||
{
|
||||
const auto q = lhs.relative() - rhs;
|
||||
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)
|
||||
requires requires(quantity_type q) { q - 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>
|
||||
[[nodiscard]] friend constexpr auto operator<=>(const quantity_point& lhs, const QP& rhs)
|
||||
{
|
||||
return lhs.relative() <=> rhs.relative();
|
||||
}
|
||||
|
||||
template<QuantityPoint QP>
|
||||
template<QuantityPointOf<origin> QP>
|
||||
requires std::equality_comparable_with<quantity_type, typename QP::quantity_type>
|
||||
[[nodiscard]] friend constexpr bool operator==(const quantity_point& lhs, const QP& rhs)
|
||||
{
|
||||
return lhs.relative() == rhs.relative();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
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>
|
||||
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>;
|
||||
|
||||
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>::rep>;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename D, typename U, typename Rep>
|
||||
inline constexpr bool is_quantity_point<quantity_point<D, U, Rep>> = true;
|
||||
template<typename O, typename U, typename Rep>
|
||||
inline constexpr bool is_quantity_point<quantity_point<O, U, Rep>> = true;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
@@ -34,7 +34,7 @@ namespace units {
|
||||
/**
|
||||
* @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 U the measurement unit of the quantity point kind
|
||||
@@ -45,6 +45,7 @@ class quantity_point_kind {
|
||||
public:
|
||||
using point_kind_type = PK;
|
||||
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_type = typename quantity_kind_type::quantity_type;
|
||||
using dimension = typename quantity_type::dimension;
|
||||
@@ -60,32 +61,28 @@ public:
|
||||
quantity_point_kind(const quantity_point_kind&) = default;
|
||||
quantity_point_kind(quantity_point_kind&&) = default;
|
||||
|
||||
template<safe_convertible_to_<rep> Value>
|
||||
requires std::is_constructible_v<quantity_kind_type, Value>
|
||||
constexpr explicit quantity_point_kind(const Value& v) : qk_(v) {}
|
||||
template<typename T>
|
||||
requires std::constructible_from<quantity_kind_type, T>
|
||||
constexpr explicit quantity_point_kind(T&& t) : qk_(std::forward<T>(t)) {}
|
||||
|
||||
constexpr explicit quantity_point_kind(const quantity_type& q) : qk_{q} {}
|
||||
|
||||
template<QuantityLike Q>
|
||||
requires std::is_constructible_v<quantity_type, Q>
|
||||
constexpr explicit quantity_point_kind(const Q& 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<QuantityPointLike QP>
|
||||
requires std::is_constructible_v<quantity_point<dimension, U, Rep>, QP>
|
||||
constexpr explicit quantity_point_kind(const QP& qp) : qk_{quantity_point_like_traits<QP>::relative(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 quantity_point<dimension, U, Rep>& qp) : qk_{qp.relative()} {}
|
||||
|
||||
constexpr explicit quantity_point_kind(const quantity_kind_type& qk) : qk_{qk} {}
|
||||
|
||||
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()} {}
|
||||
template<QuantityPointKindOf<point_kind_type> QPK2>
|
||||
requires std::convertible_to<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=(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
|
||||
requires requires { quantity_kind_type::min(); }
|
||||
@@ -163,20 +160,21 @@ public:
|
||||
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; }
|
||||
{
|
||||
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>
|
||||
[[nodiscard]] friend constexpr auto operator<=>(const quantity_point_kind& lhs, const QPK& rhs)
|
||||
{
|
||||
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>
|
||||
[[nodiscard]] friend constexpr bool operator==(const quantity_point_kind& lhs, const QPK& rhs)
|
||||
{
|
||||
|
@@ -22,11 +22,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/bits/deduced_symbol_text.h>
|
||||
#include <units/bits/derived_symbol_text.h>
|
||||
#include <units/bits/external/downcasting.h>
|
||||
|
||||
// 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/prefix.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>
|
||||
requires detail::same_scaled_units<typename Dim::recipe, U, URest...> &&
|
||||
(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 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;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @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
|
||||
*
|
||||
@@ -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>
|
||||
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 auto symbol = Symbol;
|
||||
using prefix_family = PF;
|
||||
|
@@ -50,7 +50,7 @@ using dim_modulation_rate = si::dim_frequency;
|
||||
template<UnitOf<dim_modulation_rate> U, Representation Rep = double>
|
||||
using modulation_rate = quantity<dim_modulation_rate, U, Rep>;
|
||||
|
||||
#ifdef UNITS_LITERALS
|
||||
#ifndef UNITS_NO_LITERALS
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -66,9 +66,9 @@ constexpr auto operator"" _q_YBd(unsigned long long l) { gsl_ExpectsAudit(std::i
|
||||
|
||||
} // namespace literals
|
||||
|
||||
#endif // UNITS_LITERALS
|
||||
#endif // UNITS_NO_LITERALS
|
||||
|
||||
#ifdef UNITS_REFERENCES
|
||||
#ifndef UNITS_NO_REFERENCES
|
||||
|
||||
namespace modulation_rate_references {
|
||||
|
||||
@@ -90,11 +90,11 @@ using namespace modulation_rate_references;
|
||||
|
||||
} // namespace references
|
||||
|
||||
#endif // UNITS_REFERENCES
|
||||
#endif // UNITS_NO_REFERENCES
|
||||
|
||||
} // namespace units::isq::iec80000
|
||||
|
||||
#ifdef UNITS_ALIASES
|
||||
#ifndef UNITS_NO_ALIASES
|
||||
|
||||
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
|
||||
|
||||
#endif // UNITS_ALIASES
|
||||
#endif // UNITS_NO_ALIASES
|
||||
|
@@ -79,7 +79,7 @@ concept StorageCapacity = QuantityOf<T, dim_storage_capacity>;
|
||||
template<UnitOf<dim_storage_capacity> U, Representation Rep = double>
|
||||
using storage_capacity = quantity<dim_storage_capacity, U, Rep>;
|
||||
|
||||
#ifdef UNITS_LITERALS
|
||||
#ifndef UNITS_NO_LITERALS
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -123,9 +123,9 @@ constexpr auto operator"" _q_PiB(unsigned long long l) { gsl_ExpectsAudit(std::i
|
||||
|
||||
} // namespace literals
|
||||
|
||||
#endif // UNITS_LITERALS
|
||||
#endif // UNITS_NO_LITERALS
|
||||
|
||||
#ifdef UNITS_REFERENCES
|
||||
#ifndef UNITS_NO_REFERENCES
|
||||
|
||||
namespace storage_capacity_references {
|
||||
|
||||
@@ -175,11 +175,11 @@ using namespace storage_capacity_references;
|
||||
|
||||
} // namespace references
|
||||
|
||||
#endif // UNITS_REFERENCES
|
||||
#endif // UNITS_NO_REFERENCES
|
||||
|
||||
} // namespace units::isq::iec80000
|
||||
|
||||
#ifdef UNITS_ALIASES
|
||||
#ifndef UNITS_NO_ALIASES
|
||||
|
||||
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
|
||||
|
||||
#endif // UNITS_ALIASES
|
||||
#endif // UNITS_NO_ALIASES
|
||||
|
@@ -43,7 +43,7 @@ concept TrafficIntensity = QuantityOf<T, dim_traffic_intensity>;
|
||||
template<UnitOf<dim_traffic_intensity> U, Representation Rep = double>
|
||||
using traffic_intensity = quantity<dim_traffic_intensity, U, Rep>;
|
||||
|
||||
#ifdef UNITS_LITERALS
|
||||
#ifndef UNITS_NO_LITERALS
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -51,9 +51,9 @@ constexpr auto operator"" _q_E(unsigned long long l) { gsl_ExpectsAudit(std::in_
|
||||
|
||||
} // namespace literals
|
||||
|
||||
#endif // UNITS_LITERALS
|
||||
#endif // UNITS_NO_LITERALS
|
||||
|
||||
#ifdef UNITS_REFERENCES
|
||||
#ifndef UNITS_NO_REFERENCES
|
||||
|
||||
namespace traffic_intensity_references {
|
||||
|
||||
@@ -67,11 +67,11 @@ using namespace traffic_intensity_references;
|
||||
|
||||
} // namespace references
|
||||
|
||||
#endif // UNITS_REFERENCES
|
||||
#endif // UNITS_NO_REFERENCES
|
||||
|
||||
} // namespace units::isq::iec80000
|
||||
|
||||
#ifdef UNITS_ALIASES
|
||||
#ifndef UNITS_NO_ALIASES
|
||||
|
||||
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
|
||||
|
||||
#endif // UNITS_ALIASES
|
||||
#endif // UNITS_NO_ALIASES
|
||||
|
@@ -37,14 +37,14 @@ namespace units::isq::iec80000 {
|
||||
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 kilobyte_per_second : deduced_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 gigabyte_per_second : deduced_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 petabyte_per_second : deduced_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 zettabyte_per_second : deduced_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 kilobyte_per_second : derived_unit<kilobyte_per_second, dim_transfer_rate, kilobyte, si::second> {};
|
||||
struct megabyte_per_second : derived_unit<megabyte_per_second, dim_transfer_rate, megabyte, si::second> {};
|
||||
struct gigabyte_per_second : derived_unit<gigabyte_per_second, dim_transfer_rate, gigabyte, si::second> {};
|
||||
struct terabyte_per_second : derived_unit<terabyte_per_second, dim_transfer_rate, terabyte, si::second> {};
|
||||
struct petabyte_per_second : derived_unit<petabyte_per_second, dim_transfer_rate, petabyte, si::second> {};
|
||||
struct exabyte_per_second : derived_unit<exabyte_per_second, dim_transfer_rate, exabyte, si::second> {};
|
||||
struct zettabyte_per_second : derived_unit<zettabyte_per_second, dim_transfer_rate, zettabyte, si::second> {};
|
||||
struct yottabyte_per_second : derived_unit<yottabyte_per_second, dim_transfer_rate, yottabyte, si::second> {};
|
||||
|
||||
template<typename T>
|
||||
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>
|
||||
using transfer_rate = quantity<dim_transfer_rate, U, Rep>;
|
||||
|
||||
#ifdef UNITS_LITERALS
|
||||
#ifndef UNITS_NO_LITERALS
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -68,11 +68,11 @@ constexpr auto operator"" _q_YB_per_s(unsigned long long l) { gsl_ExpectsAudit(s
|
||||
|
||||
} // namespace literals
|
||||
|
||||
#endif // UNITS_LITERALS
|
||||
#endif // UNITS_NO_LITERALS
|
||||
|
||||
} // namespace units::isq::iec80000
|
||||
|
||||
#ifdef UNITS_ALIASES
|
||||
#ifndef UNITS_NO_ALIASES
|
||||
|
||||
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
|
||||
|
||||
#endif // UNITS_ALIASES
|
||||
#endif // UNITS_NO_ALIASES
|
||||
|
@@ -40,7 +40,7 @@ struct dim_acceleration : isq::dim_acceleration<dim_acceleration, gigaelectronvo
|
||||
template<UnitOf<dim_acceleration> U, Representation Rep = double>
|
||||
using acceleration = quantity<dim_acceleration, U, Rep>;
|
||||
|
||||
#ifdef UNITS_REFERENCES
|
||||
#ifndef UNITS_NO_REFERENCES
|
||||
|
||||
namespace acceleration_references {
|
||||
|
||||
@@ -54,11 +54,11 @@ using namespace acceleration_references;
|
||||
|
||||
} // namespace references
|
||||
|
||||
#endif // UNITS_REFERENCES
|
||||
#endif // UNITS_NO_REFERENCES
|
||||
|
||||
} // namespace units::isq::natural
|
||||
|
||||
#ifdef UNITS_ALIASES
|
||||
#ifndef UNITS_NO_ALIASES
|
||||
|
||||
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
|
||||
|
||||
#endif // UNITS_ALIASES
|
||||
#endif // UNITS_NO_ALIASES
|
||||
|
@@ -40,7 +40,7 @@ struct dim_energy : isq::dim_energy<dim_energy, gigaelectronvolt, dim_force, dim
|
||||
template<UnitOf<dim_energy> U, Representation Rep = double>
|
||||
using energy = quantity<dim_energy, U, Rep>;
|
||||
|
||||
#ifdef UNITS_REFERENCES
|
||||
#ifndef UNITS_NO_REFERENCES
|
||||
|
||||
namespace energy_references {
|
||||
|
||||
@@ -54,11 +54,11 @@ using namespace energy_references;
|
||||
|
||||
} // namespace references
|
||||
|
||||
#endif // UNITS_REFERENCES
|
||||
#endif // UNITS_NO_REFERENCES
|
||||
|
||||
} // namespace units::isq::natural
|
||||
|
||||
#ifdef UNITS_ALIASES
|
||||
#ifndef UNITS_NO_ALIASES
|
||||
|
||||
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
|
||||
|
||||
#endif // UNITS_ALIASES
|
||||
#endif // UNITS_NO_ALIASES
|
||||
|
@@ -40,7 +40,7 @@ struct dim_force : isq::dim_force<dim_force, square_gigaelectronvolt, dim_mass,
|
||||
template<UnitOf<dim_force> U, Representation Rep = double>
|
||||
using force = quantity<dim_force, U, Rep>;
|
||||
|
||||
#ifdef UNITS_REFERENCES
|
||||
#ifndef UNITS_NO_REFERENCES
|
||||
|
||||
namespace force_references {
|
||||
|
||||
@@ -54,11 +54,11 @@ using namespace force_references;
|
||||
|
||||
} // namespace references
|
||||
|
||||
#endif // UNITS_REFERENCES
|
||||
#endif // UNITS_NO_REFERENCES
|
||||
|
||||
} // namespace units::isq::natural
|
||||
|
||||
#ifdef UNITS_ALIASES
|
||||
#ifndef UNITS_NO_ALIASES
|
||||
|
||||
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
|
||||
|
||||
#endif // UNITS_ALIASES
|
||||
#endif // UNITS_NO_ALIASES
|
||||
|
@@ -37,7 +37,7 @@ struct dim_length : isq::dim_length<inverted_gigaelectronvolt> {};
|
||||
template<UnitOf<dim_length> U, Representation Rep = double>
|
||||
using length = quantity<dim_length, U, Rep>;
|
||||
|
||||
#ifdef UNITS_REFERENCES
|
||||
#ifndef UNITS_NO_REFERENCES
|
||||
|
||||
namespace length_references {
|
||||
|
||||
@@ -51,11 +51,11 @@ using namespace length_references;
|
||||
|
||||
} // namespace references
|
||||
|
||||
#endif // UNITS_REFERENCES
|
||||
#endif // UNITS_NO_REFERENCES
|
||||
|
||||
} // namespace units::isq::natural
|
||||
|
||||
#ifdef UNITS_ALIASES
|
||||
#ifndef UNITS_NO_ALIASES
|
||||
|
||||
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
|
||||
|
||||
#endif // UNITS_ALIASES
|
||||
#endif // UNITS_NO_ALIASES
|
||||
|
@@ -37,7 +37,7 @@ struct dim_mass : isq::dim_mass<gigaelectronvolt> {};
|
||||
template<UnitOf<dim_mass> U, Representation Rep = double>
|
||||
using mass = quantity<dim_mass, U, Rep>;
|
||||
|
||||
#ifdef UNITS_REFERENCES
|
||||
#ifndef UNITS_NO_REFERENCES
|
||||
|
||||
namespace mass_references {
|
||||
|
||||
@@ -51,11 +51,11 @@ using namespace mass_references;
|
||||
|
||||
} // namespace references
|
||||
|
||||
#endif // UNITS_REFERENCES
|
||||
#endif // UNITS_NO_REFERENCES
|
||||
|
||||
} // namespace units::isq::natural
|
||||
|
||||
#ifdef UNITS_ALIASES
|
||||
#ifndef UNITS_NO_ALIASES
|
||||
|
||||
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
|
||||
|
||||
#endif // UNITS_ALIASES
|
||||
#endif // UNITS_NO_ALIASES
|
||||
|
@@ -40,7 +40,7 @@ struct dim_momentum : isq::dim_momentum<dim_momentum, gigaelectronvolt, dim_mass
|
||||
template<UnitOf<dim_momentum> U, Representation Rep = double>
|
||||
using momentum = quantity<dim_momentum, U, Rep>;
|
||||
|
||||
#ifdef UNITS_REFERENCES
|
||||
#ifndef UNITS_NO_REFERENCES
|
||||
|
||||
namespace momentum_references {
|
||||
|
||||
@@ -54,11 +54,11 @@ using namespace momentum_references;
|
||||
|
||||
} // namespace references
|
||||
|
||||
#endif // UNITS_REFERENCES
|
||||
#endif // UNITS_NO_REFERENCES
|
||||
|
||||
} // namespace units::isq::natural
|
||||
|
||||
#ifdef UNITS_ALIASES
|
||||
#ifndef UNITS_NO_ALIASES
|
||||
|
||||
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
|
||||
|
||||
#endif // UNITS_ALIASES
|
||||
#endif // UNITS_NO_ALIASES
|
||||
|
@@ -37,7 +37,7 @@ struct dim_time : isq::dim_time<inverted_gigaelectronvolt> {};
|
||||
template<UnitOf<dim_time> U, Representation Rep = double>
|
||||
using time = quantity<dim_time, U, Rep>;
|
||||
|
||||
#ifdef UNITS_REFERENCES
|
||||
#ifndef UNITS_NO_REFERENCES
|
||||
|
||||
namespace time_references {
|
||||
|
||||
@@ -51,11 +51,11 @@ using namespace time_references;
|
||||
|
||||
} // namespace references
|
||||
|
||||
#endif // UNITS_REFERENCES
|
||||
#endif // UNITS_NO_REFERENCES
|
||||
|
||||
} // namespace units::isq::natural
|
||||
|
||||
#ifdef UNITS_ALIASES
|
||||
#ifndef UNITS_NO_ALIASES
|
||||
|
||||
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
|
||||
|
||||
#endif // UNITS_ALIASES
|
||||
#endif // UNITS_NO_ALIASES
|
||||
|
@@ -28,8 +28,11 @@
|
||||
|
||||
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>
|
||||
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>
|
||||
concept AbsorbedDose = QuantityOfT<T, dim_absorbed_dose>;
|
||||
|
@@ -28,8 +28,11 @@
|
||||
|
||||
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>
|
||||
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>
|
||||
concept Acceleration = QuantityOfT<T, dim_acceleration>;
|
||||
|
@@ -28,8 +28,11 @@
|
||||
|
||||
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>
|
||||
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>
|
||||
concept AngularVelocity = QuantityOfT<T, dim_angular_velocity>;
|
||||
|
@@ -27,8 +27,11 @@
|
||||
|
||||
namespace units::isq {
|
||||
|
||||
template<typename Child, Unit U, typename...>
|
||||
struct dim_area;
|
||||
|
||||
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>
|
||||
concept Area = QuantityOfT<T, dim_area>;
|
||||
|
@@ -28,8 +28,11 @@
|
||||
|
||||
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>
|
||||
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>
|
||||
concept Capacitance = QuantityOfT<T, dim_capacitance>;
|
||||
|
@@ -28,8 +28,11 @@
|
||||
|
||||
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>
|
||||
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>
|
||||
concept CatalyticActivity = QuantityOfT<T, dim_catalytic_activity>;
|
||||
|
@@ -28,11 +28,17 @@
|
||||
|
||||
namespace units::isq {
|
||||
|
||||
template<typename Child, Unit U, DimensionOfT<dim_electric_charge> Q, DimensionOfT<dim_length> L>
|
||||
struct dim_charge_density : derived_dimension<Child, U, exponent<Q, 1>, exponent<L, -3>> {};
|
||||
template<typename Child, Unit U, typename...>
|
||||
struct dim_charge_density;
|
||||
|
||||
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>
|
||||
concept ChargeDensity = QuantityOfT<T, dim_charge_density>;
|
||||
|
@@ -28,8 +28,11 @@
|
||||
|
||||
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>
|
||||
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>
|
||||
concept Concentration = QuantityOfT<T, dim_concentration>;
|
||||
|
@@ -27,8 +27,11 @@
|
||||
|
||||
namespace units::isq {
|
||||
|
||||
template<typename Child, Unit U, typename...>
|
||||
struct dim_conductance;
|
||||
|
||||
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>
|
||||
concept Conductance = QuantityOfT<T, dim_conductance>;
|
||||
|
@@ -28,8 +28,11 @@
|
||||
|
||||
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>
|
||||
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>
|
||||
concept CurrentDensity = QuantityOfT<T, dim_current_density>;
|
||||
|
@@ -28,8 +28,11 @@
|
||||
|
||||
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>
|
||||
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>
|
||||
concept Density = QuantityOfT<T, dim_density>;
|
||||
|
@@ -28,8 +28,11 @@
|
||||
|
||||
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>
|
||||
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>
|
||||
concept DynamicViscosity = QuantityOfT<T, dim_dynamic_viscosity>;
|
||||
|
@@ -28,8 +28,11 @@
|
||||
|
||||
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>
|
||||
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>
|
||||
concept ElectricCharge = QuantityOfT<T, dim_electric_charge>;
|
||||
|
@@ -28,8 +28,11 @@
|
||||
|
||||
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>
|
||||
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>
|
||||
concept ElectricFieldStrength = QuantityOfT<T, dim_electric_field_strength>;
|
||||
|
@@ -28,8 +28,14 @@
|
||||
|
||||
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>
|
||||
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>
|
||||
concept Energy = QuantityOfT<T, dim_energy>;
|
||||
|
@@ -28,8 +28,11 @@
|
||||
|
||||
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>
|
||||
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>
|
||||
concept EnergyDensity = QuantityOfT<T, dim_energy_density>;
|
||||
|
@@ -28,8 +28,11 @@
|
||||
|
||||
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>
|
||||
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>
|
||||
concept Force = QuantityOfT<T, dim_force>;
|
||||
|
@@ -27,8 +27,11 @@
|
||||
|
||||
namespace units::isq {
|
||||
|
||||
template<typename Child, Unit U, typename...>
|
||||
struct dim_frequency;
|
||||
|
||||
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>
|
||||
concept Frequency = QuantityOfT<T, dim_frequency>;
|
||||
|
@@ -30,14 +30,23 @@
|
||||
|
||||
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>
|
||||
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>
|
||||
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>
|
||||
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>
|
||||
concept HeatCapacity = QuantityOfT<T, dim_heat_capacity>;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user