forked from mpusz/mp-units
Merge branch 'mpusz:master' into master
This commit is contained in:
@@ -63,7 +63,7 @@ CommentPragmas: '^ NOLINT'
|
|||||||
# CompactNamespaces: false
|
# CompactNamespaces: false
|
||||||
# ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
# ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
# ConstructorInitializerIndentWidth: 4
|
# ConstructorInitializerIndentWidth: 4
|
||||||
# ContinuationIndentWidth: 4
|
ContinuationIndentWidth: 2
|
||||||
# Cpp11BracedListStyle: true
|
# Cpp11BracedListStyle: true
|
||||||
DeriveLineEnding: false
|
DeriveLineEnding: false
|
||||||
DerivePointerAlignment: false
|
DerivePointerAlignment: false
|
||||||
@@ -109,7 +109,7 @@ IndentRequires: true
|
|||||||
# KeepEmptyLinesAtTheStartOfBlocks: false
|
# KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
# MacroBlockBegin: ''
|
# MacroBlockBegin: ''
|
||||||
# MacroBlockEnd: ''
|
# MacroBlockEnd: ''
|
||||||
# MaxEmptyLinesToKeep: 1
|
MaxEmptyLinesToKeep: 2
|
||||||
# NamespaceIndentation: None
|
# NamespaceIndentation: None
|
||||||
# ObjCBinPackProtocolList: Never
|
# ObjCBinPackProtocolList: Never
|
||||||
# ObjCBlockIndentWidth: 2
|
# ObjCBlockIndentWidth: 2
|
||||||
|
11
.github/workflows/ci-conan.yml
vendored
11
.github/workflows/ci-conan.yml
vendored
@@ -78,6 +78,11 @@ jobs:
|
|||||||
downcast_mode: [ "on", "auto" ]
|
downcast_mode: [ "on", "auto" ]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
- uses: hendrikmuhs/ccache-action@v1
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
with:
|
||||||
|
key: ${{ matrix.config.os }}-${{ matrix.config.compiler.type }}-${{ matrix.config.compiler.version }}-${{ matrix.config.lib }}-${{ matrix.build_type }}-${{ matrix.downcast_mode }}
|
||||||
|
max-size: 50M
|
||||||
- name: Install Clang
|
- name: Install Clang
|
||||||
if: matrix.config.compiler.type == 'CLANG'
|
if: matrix.config.compiler.type == 'CLANG'
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -121,12 +126,6 @@ jobs:
|
|||||||
conan profile update settings.compiler.libcxx=${{ matrix.config.lib }} default
|
conan profile update settings.compiler.libcxx=${{ matrix.config.lib }} default
|
||||||
fi
|
fi
|
||||||
conan profile show default
|
conan profile show default
|
||||||
- name: Add support for clang-12 to Conan's settings.yml
|
|
||||||
# TODO Remove when Conan will support clang-12 (after clang-12 release)
|
|
||||||
if: matrix.config.compiler.type == 'CLANG'
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
sed -i -e 's/"8", "9", "10", "11"]/"8", "9", "10", "11", "12"]/' ~/.conan/settings.yml
|
|
||||||
- name: Run Conan Package Tools
|
- name: Run Conan Package Tools
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
|
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 }}
|
CC: ${{ matrix.config.compiler.cc }}
|
||||||
CXX: ${{ matrix.config.compiler.cxx }}
|
CXX: ${{ matrix.config.compiler.cxx }}
|
||||||
CMAKE_GENERATOR: Ninja
|
CMAKE_GENERATOR: Ninja
|
||||||
|
CONAN_CMAKE_GENERATOR: Ninja
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
@@ -143,18 +144,20 @@ jobs:
|
|||||||
conan profile update settings.compiler.libcxx=${{ matrix.config.lib }} default
|
conan profile update settings.compiler.libcxx=${{ matrix.config.lib }} default
|
||||||
fi
|
fi
|
||||||
conan profile show default
|
conan profile show default
|
||||||
- name: Add support for clang-12 to Conan's settings.yml
|
|
||||||
# TODO Remove when Conan will support clang-12 (after clang-12 release)
|
|
||||||
if: matrix.config.compiler.type == 'CLANG'
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
sed -i -e 's/"8", "9", "10", "11"]/"8", "9", "10", "11", "12"]/' ~/.conan/settings.yml
|
|
||||||
- name: Install Conan dependencies
|
- name: Install Conan dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
mkdir -p build/${{ matrix.build_type }} && cd build/${{ matrix.build_type }}
|
mkdir -p build/${{ matrix.build_type }} && cd build/${{ matrix.build_type }}
|
||||||
conan install ../.. -b outdated -u
|
conan install ../.. -b outdated -u
|
||||||
- name: Configure mp-units CMake
|
- name: Configure mp-units CMake
|
||||||
|
if: matrix.config.compiler.type == 'VISUAL'
|
||||||
|
shell: cmd
|
||||||
|
working-directory: build/${{ matrix.build_type }}
|
||||||
|
run: |
|
||||||
|
call conanvcvars.bat
|
||||||
|
cmake ../../src -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
|
||||||
|
- name: Configure mp-units CMake
|
||||||
|
if: matrix.config.compiler.type != 'VISUAL'
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: build/${{ matrix.build_type }}
|
working-directory: build/${{ matrix.build_type }}
|
||||||
run: |
|
run: |
|
||||||
@@ -164,16 +167,25 @@ jobs:
|
|||||||
working-directory: build/${{ matrix.build_type }}
|
working-directory: build/${{ matrix.build_type }}
|
||||||
run: |
|
run: |
|
||||||
cmake --install . --prefix test_package
|
cmake --install . --prefix test_package
|
||||||
- name: Configure test_package CMake
|
- name: Install dependencies for test_package
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
mkdir -p test_package/build/${{ matrix.build_type }} && cd test_package/build/${{ matrix.build_type }}
|
mkdir -p test_package/build/${{ matrix.build_type }} && cd test_package/build/${{ matrix.build_type }}
|
||||||
conan install ../../..
|
conan install ../../..
|
||||||
|
- name: Build test_package CMake
|
||||||
|
if: matrix.config.compiler.type == 'VISUAL'
|
||||||
|
shell: cmd
|
||||||
|
working-directory: test_package/build/${{ matrix.build_type }}
|
||||||
|
run: |
|
||||||
|
call conanvcvars.bat
|
||||||
cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_INSTALL_PREFIX=../../../build/${{ matrix.build_type }}/test_package
|
cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_INSTALL_PREFIX=../../../build/${{ matrix.build_type }}/test_package
|
||||||
- name: Build test_package
|
cmake --build .
|
||||||
|
- name: Build test_package CMake
|
||||||
|
if: matrix.config.compiler.type != 'VISUAL'
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: test_package/build/${{ matrix.build_type }}
|
working-directory: test_package/build/${{ matrix.build_type }}
|
||||||
run: |
|
run: |
|
||||||
|
cmake ../.. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_INSTALL_PREFIX=../../../build/${{ matrix.build_type }}/test_package
|
||||||
cmake --build .
|
cmake --build .
|
||||||
- name: Run test_package
|
- name: Run test_package
|
||||||
shell: bash
|
shell: bash
|
||||||
|
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@@ -84,7 +84,7 @@ jobs:
|
|||||||
pip install -U conan
|
pip install -U conan
|
||||||
conan config init
|
conan config init
|
||||||
conan remote add upload https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
conan remote add upload https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
||||||
conan remote add linear-algebra https://api.bintray.com/conan/twonington/public-conan
|
conan remote add linear-algebra https://twonington.jfrog.io/artifactory/api/conan/conan-oss
|
||||||
mkdir _lgtm_build_dir && cd _lgtm_build_dir
|
mkdir _lgtm_build_dir && cd _lgtm_build_dir
|
||||||
conan install .. -s compiler.cppstd=20 -s compiler.libcxx=libstdc++11 -o mp-units:build_docs=False -e mp-units:CONAN_RUN_TESTS=True -b outdated -u
|
conan install .. -s compiler.cppstd=20 -s compiler.libcxx=libstdc++11 -o mp-units:build_docs=False -e mp-units:CONAN_RUN_TESTS=True -b outdated -u
|
||||||
conan build ..
|
conan build ..
|
||||||
|
3
.github/workflows/documentation.yml
vendored
3
.github/workflows/documentation.yml
vendored
@@ -40,6 +40,7 @@ env:
|
|||||||
CC: gcc-10
|
CC: gcc-10
|
||||||
CXX: g++-10
|
CXX: g++-10
|
||||||
CMAKE_GENERATOR: Ninja
|
CMAKE_GENERATOR: Ninja
|
||||||
|
CONAN_CMAKE_GENERATOR: Ninja
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docs:
|
docs:
|
||||||
@@ -75,7 +76,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
conan config init
|
conan config init
|
||||||
conan remote add -i 0 upload https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
conan remote add -i 0 upload https://mpusz.jfrog.io/artifactory/api/conan/conan-oss
|
||||||
conan remote add linear-algebra https://api.bintray.com/conan/twonington/public-conan
|
conan remote add linear-algebra https://twonington.jfrog.io/artifactory/api/conan/conan-oss
|
||||||
- name: Install Conan dependencies
|
- name: Install Conan dependencies
|
||||||
run: |
|
run: |
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -38,6 +38,7 @@
|
|||||||
/cmake-build-*/
|
/cmake-build-*/
|
||||||
/build/
|
/build/
|
||||||
/out/
|
/out/
|
||||||
|
_build/
|
||||||
|
|
||||||
# Conan
|
# Conan
|
||||||
*.pyc
|
*.pyc
|
||||||
|
@@ -27,6 +27,14 @@ project(mp-units-dev
|
|||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
|
# make sure that the file is being used as an entry point
|
||||||
|
include(modern_project_structure)
|
||||||
|
ensure_entry_point()
|
||||||
|
|
||||||
|
# use ccache if available
|
||||||
|
include(ccache)
|
||||||
|
enable_ccache(BASE_DIR ${PROJECT_SOURCE_DIR})
|
||||||
|
|
||||||
# set restrictive compilation warnings
|
# set restrictive compilation warnings
|
||||||
include(warnings)
|
include(warnings)
|
||||||
set_warnings()
|
set_warnings()
|
||||||
@@ -38,7 +46,7 @@ add_compile_definitions($<$<CONFIG:Debug>:gsl_CONFIG_CONTRACT_CHECKING_AUDIT>)
|
|||||||
option(UNITS_IWYU "Enables include-what-you-use" OFF)
|
option(UNITS_IWYU "Enables include-what-you-use" OFF)
|
||||||
if(UNITS_IWYU)
|
if(UNITS_IWYU)
|
||||||
include(include-what-you-use)
|
include(include-what-you-use)
|
||||||
set_iwyu(
|
enable_iwyu(
|
||||||
MAPPING_FILE "${PROJECT_SOURCE_DIR}/.mp-units.imp"
|
MAPPING_FILE "${PROJECT_SOURCE_DIR}/.mp-units.imp"
|
||||||
NO_FORWARD_DECLARATIONS
|
NO_FORWARD_DECLARATIONS
|
||||||
QUOTED_INCLUDES_FIRST
|
QUOTED_INCLUDES_FIRST
|
||||||
|
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%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%3A%22CMake+Test+Package+CI%22+branch%3Amaster)
|
||||||
[](https://github.com/mpusz/units/actions?query=workflow%3ADocumentation+branch%3Amaster)
|
[](https://github.com/mpusz/units/actions?query=workflow%3ADocumentation+branch%3Amaster)
|
||||||
[](https://conan.io/center/mp-units)
|
[](https://conan.io/center/mp-units)
|
||||||
[](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units/0.7.0)
|
[](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units/0.8.0)
|
||||||
|
|
||||||
# `mp-units` - A Units Library for C++
|
# `mp-units` - A Units Library for C++
|
||||||
|
|
||||||
@@ -28,8 +28,6 @@ analysis and unit/quantity manipulation. The basic idea and design heavily bases
|
|||||||
Here is a small example of possible operations:
|
Here is a small example of possible operations:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#define UNITS_REFERENCES
|
|
||||||
|
|
||||||
#include <units/isq/si/area.h>
|
#include <units/isq/si/area.h>
|
||||||
#include <units/isq/si/frequency.h>
|
#include <units/isq/si/frequency.h>
|
||||||
#include <units/isq/si/length.h>
|
#include <units/isq/si/length.h>
|
||||||
@@ -58,7 +56,7 @@ static_assert(10 * km / (5 * km) == 2);
|
|||||||
static_assert(1000 / (1 * s) == 1 * kHz);
|
static_assert(1000 / (1 * s) == 1 * kHz);
|
||||||
```
|
```
|
||||||
|
|
||||||
_Try it on the [Compiler Explorer](https://godbolt.org/z/53bTahKd8)._
|
_Try it on the [Compiler Explorer](https://godbolt.org/z/5dvY8Woh1)._
|
||||||
|
|
||||||
This library requires some C++20 features (concepts, classes as NTTPs, ...). Thanks to
|
This library requires some C++20 features (concepts, classes as NTTPs, ...). Thanks to
|
||||||
them the user gets a powerful but still easy to use interface and all unit conversions
|
them the user gets a powerful but still easy to use interface and all unit conversions
|
||||||
@@ -66,10 +64,6 @@ and dimensional analysis can be performed without sacrificing on accuracy. Pleas
|
|||||||
the below example for a quick preview of basic library features:
|
the below example for a quick preview of basic library features:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#define UNITS_ALIASES
|
|
||||||
#define UNITS_LITERALS
|
|
||||||
#define UNITS_REFERENCES
|
|
||||||
|
|
||||||
#include <units/format.h>
|
#include <units/format.h>
|
||||||
#include <units/isq/si/international/length.h>
|
#include <units/isq/si/international/length.h>
|
||||||
#include <units/isq/si/international/speed.h>
|
#include <units/isq/si/international/speed.h>
|
||||||
@@ -115,4 +109,4 @@ int main()
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
_Try it on the [Compiler Explorer](https://godbolt.org/z/jKnPPPEx6)._
|
_Try it on the [Compiler Explorer](https://godbolt.org/z/9fnzfbhb6)._
|
||||||
|
2
build.py
2
build.py
@@ -36,7 +36,7 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
remotes = [
|
remotes = [
|
||||||
("https://api.bintray.com/conan/twonington/public-conan", True, "linear-algebra")
|
("https://twonington.jfrog.io/artifactory/api/conan/conan-oss", True, "linear-algebra")
|
||||||
],
|
],
|
||||||
build_policy = ["mp-units", "outdated"],
|
build_policy = ["mp-units", "outdated"],
|
||||||
upload_dependencies = "all",
|
upload_dependencies = "all",
|
||||||
|
221
cmake/ccache.cmake
Normal file
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)
|
if(NOT _args_DOXYFILE_TEMPLATE)
|
||||||
set(_args_DOXYFILE_TEMPLATE Doxyfile.in)
|
set(_args_DOXYFILE_TEMPLATE Doxyfile.in)
|
||||||
endif()
|
endif()
|
||||||
file(REAL_PATH ${_args_DOXYFILE_TEMPLATE} _doxyfileIn)
|
get_filename_component(_doxyfileIn ${_args_DOXYFILE_TEMPLATE} REALPATH)
|
||||||
if(NOT EXISTS ${_doxyfileIn})
|
if(NOT EXISTS ${_doxyfileIn})
|
||||||
message(FATAL_ERROR "'${_args_DOXYFILE_TEMPLATE}' does not exist")
|
message(FATAL_ERROR "'${_args_DOXYFILE_TEMPLATE}' does not exist")
|
||||||
endif()
|
endif()
|
||||||
|
@@ -30,53 +30,82 @@ endif()
|
|||||||
|
|
||||||
set(IWYU_VERBOSITY_LEVEL 3 CACHE STRING "IWYU verbosity level (the higher the level, the more output)")
|
set(IWYU_VERBOSITY_LEVEL 3 CACHE STRING "IWYU verbosity level (the higher the level, the more output)")
|
||||||
|
|
||||||
macro(_find_iwyu)
|
|
||||||
find_program(_iwyu_path NAMES "include-what-you-use")
|
|
||||||
if(NOT _iwyu_path)
|
|
||||||
message(WARNING "'include-what-you-use' executable not found!")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
macro(_iwyu_args_append arg)
|
macro(_iwyu_args_append arg)
|
||||||
list(APPEND _iwyu_args "-Xiwyu" "${arg}")
|
list(APPEND _iwyu_args "-Xiwyu" "${arg}")
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
macro(_iwyu_args_append_if_present option arg)
|
macro(_iwyu_args_append_if_present option arg)
|
||||||
if(_set_iwyu_${option})
|
if(_enable_iwyu_${option})
|
||||||
_iwyu_args_append("${arg}")
|
_iwyu_args_append("${arg}")
|
||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
macro(_process_iwyu_arguments offset)
|
macro(_enable_iwyu_failed log_postfix)
|
||||||
set(_options NO_DEFAULT_MAPPINGS PCH_IN_CODE TRANSITIVE_INCLUDES_ONLY NO_COMMENTS NO_FORWARD_DECLARATIONS CXX17_NAMESPACES QUOTED_INCLUDES_FIRST)
|
if(NOT _enable_iwyu_QUIET)
|
||||||
set(_one_value_args MAPPING_FILE MAX_LINE_LENGTH)
|
message(STATUS "Enabling include-what-you-use${log_postfix} - failed")
|
||||||
|
endif()
|
||||||
|
return()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(_process_iwyu_arguments offset log_postfix)
|
||||||
|
set(_options QUIET REQUIRED NO_DEFAULT_MAPPINGS PCH_IN_CODE TRANSITIVE_INCLUDES_ONLY NO_COMMENTS NO_FORWARD_DECLARATIONS CXX17_NAMESPACES QUOTED_INCLUDES_FIRST)
|
||||||
|
set(_one_value_args PROGRAM MAPPING_FILE MAX_LINE_LENGTH)
|
||||||
set(_multi_value_args KEEP)
|
set(_multi_value_args KEEP)
|
||||||
cmake_parse_arguments(PARSE_ARGV ${offset} _set_iwyu "${_options}" "${_one_value_args}" "${_multi_value_args}")
|
cmake_parse_arguments(PARSE_ARGV ${offset} _enable_iwyu "${_options}" "${_one_value_args}" "${_multi_value_args}")
|
||||||
|
|
||||||
# validate and process arguments
|
# validate and process arguments
|
||||||
if(${prefix}_UNPARSED_ARGUMENTS)
|
if(_enable_iwyu_UNPARSED_ARGUMENTS)
|
||||||
message(FATAL_ERROR "Invalid arguments '${${prefix}_UNPARSED_ARGUMENTS}'")
|
message(FATAL_ERROR "Invalid arguments '${_enable_iwyu_UNPARSED_ARGUMENTS}'")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(_set_iwyu_KEEP)
|
if(_enable_iwyu_KEYWORDS_MISSING_VALUES)
|
||||||
foreach(_pattern ${_set_iwyu_KEEP})
|
message(FATAL_ERROR "No value provided for '${_enable_iwyu_KEYWORDS_MISSING_VALUES}'")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT _enable_iwyu_QUIET)
|
||||||
|
message(STATUS "Enabling include-what-you-use${log_postfix}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(${_enable_iwyu_REQUIRED})
|
||||||
|
set(_error_log_level FATAL_ERROR)
|
||||||
|
elseif(NOT _enable_iwyu_QUIET)
|
||||||
|
set(_error_log_level STATUS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED _enable_iwyu_PROGRAM)
|
||||||
|
set(_enable_iwyu_PROGRAM include-what-you-use)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_program(IWYU_PATH ${_enable_iwyu_PROGRAM})
|
||||||
|
if(IWYU_PATH)
|
||||||
|
if(NOT _enable_iwyu_QUIET)
|
||||||
|
message(STATUS " Executable: ${IWYU_PATH}")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if(DEFINED _error_log_level)
|
||||||
|
message(${_error_log_level} " '${_enable_iwyu_PROGRAM}' executable was not found")
|
||||||
|
endif()
|
||||||
|
_enable_iwyu_failed("${log_postfix}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(_enable_iwyu_KEEP)
|
||||||
|
foreach(_pattern ${_enable_iwyu_KEEP})
|
||||||
_iwyu_args_append("--keep=${_pattern}")
|
_iwyu_args_append("--keep=${_pattern}")
|
||||||
endforeach()
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(_set_iwyu_MAPPING_FILE)
|
if(_enable_iwyu_MAPPING_FILE)
|
||||||
if(NOT EXISTS ${_set_iwyu_MAPPING_FILE})
|
if(NOT EXISTS ${_enable_iwyu_MAPPING_FILE})
|
||||||
message(FATAL_ERROR "IWYU: Mapping file '${_set_iwyu_MAPPING_FILE}' does not exist")
|
message(FATAL_ERROR "IWYU: Mapping file '${_enable_iwyu_MAPPING_FILE}' does not exist")
|
||||||
endif()
|
endif()
|
||||||
_iwyu_args_append("--mapping_file=${_set_iwyu_MAPPING_FILE}")
|
_iwyu_args_append("--mapping_file=${_enable_iwyu_MAPPING_FILE}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(_set_iwyu_MAX_LINE_LENGTH)
|
if(_enable_iwyu_MAX_LINE_LENGTH)
|
||||||
if(NOT _set_iwyu_MAX_LINE_LENGTH GREATER 0)
|
if(NOT _enable_iwyu_MAX_LINE_LENGTH GREATER 0)
|
||||||
message(FATAL_ERROR "IWYU: Invalid MAX_LINE_LENGTH value = '${_set_iwyu_MAX_LINE_LENGTH}")
|
message(FATAL_ERROR "IWYU: Invalid MAX_LINE_LENGTH value = '${_enable_iwyu_MAX_LINE_LENGTH}")
|
||||||
endif()
|
endif()
|
||||||
_iwyu_args_append("--max_line_length=${_set_iwyu_MAX_LINE_LENGTH}")
|
_iwyu_args_append("--max_line_length=${_enable_iwyu_MAX_LINE_LENGTH}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
_iwyu_args_append_if_present(NO_DEFAULT_MAPPINGS "--no_default_mappings")
|
_iwyu_args_append_if_present(NO_DEFAULT_MAPPINGS "--no_default_mappings")
|
||||||
@@ -88,10 +117,36 @@ macro(_process_iwyu_arguments offset)
|
|||||||
_iwyu_args_append_if_present(QUOTED_INCLUDES_FIRST "--quoted_includes_first")
|
_iwyu_args_append_if_present(QUOTED_INCLUDES_FIRST "--quoted_includes_first")
|
||||||
|
|
||||||
_iwyu_args_append("--verbose=${IWYU_VERBOSITY_LEVEL}")
|
_iwyu_args_append("--verbose=${IWYU_VERBOSITY_LEVEL}")
|
||||||
|
|
||||||
|
if(NOT _enable_iwyu_QUIET)
|
||||||
|
message(STATUS " Arguments: ${_iwyu_args}")
|
||||||
|
message(STATUS "Enabling include-what-you-use${log_postfix} - done")
|
||||||
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
#
|
#
|
||||||
# set_target_iwyu(TargetName
|
# enable_iwyu([PROGRAM] # include-what-you-use by default
|
||||||
|
# [QUIET] [REQUIRED]
|
||||||
|
# [KEEP patterns...]
|
||||||
|
# [MAPPING_FILE file]
|
||||||
|
# [NO_DEFAULT_MAPPINGS]
|
||||||
|
# [PCH_IN_CODE]
|
||||||
|
# [TRANSITIVE_INCLUDES_ONLY]
|
||||||
|
# [MAX_LINE_LENGTH length]
|
||||||
|
# [NO_COMMENTS]
|
||||||
|
# [NO_FORWARD_DECLARATIONS]
|
||||||
|
# [CXX17_NAMESPACES]
|
||||||
|
# [QUOTED_INCLUDES_FIRST])
|
||||||
|
#
|
||||||
|
function(enable_iwyu)
|
||||||
|
_process_iwyu_arguments(0 "")
|
||||||
|
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "${_iwyu_path};${_iwyu_args}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
#
|
||||||
|
# enable_target_iwyu(TargetName
|
||||||
|
# [PROGRAM] # include-what-you-use by default
|
||||||
|
# [QUIET] [REQUIRED]
|
||||||
# [KEEP pattern...]
|
# [KEEP pattern...]
|
||||||
# [MAPPING_FILE file]
|
# [MAPPING_FILE file]
|
||||||
# [NO_DEFAULT_MAPPINGS]
|
# [NO_DEFAULT_MAPPINGS]
|
||||||
@@ -103,40 +158,9 @@ endmacro()
|
|||||||
# [CXX17_NAMESPACES]
|
# [CXX17_NAMESPACES]
|
||||||
# [QUOTED_INCLUDES_FIRST])
|
# [QUOTED_INCLUDES_FIRST])
|
||||||
#
|
#
|
||||||
function(set_target_iwyu target)
|
function(enable_target_iwyu target)
|
||||||
_find_iwyu()
|
_process_iwyu_arguments(1 " for '${target}'")
|
||||||
_process_iwyu_arguments(1)
|
|
||||||
|
|
||||||
message(STATUS "Setting include-what-you-use for '${target}'")
|
|
||||||
message(STATUS " Path: ${_iwyu_path}")
|
|
||||||
message(STATUS " Arguments: ${_iwyu_args}")
|
|
||||||
message(STATUS "Setting include-what-you-use for '${target}' - done")
|
|
||||||
|
|
||||||
set_target_properties(${target} PROPERTIES
|
set_target_properties(${target} PROPERTIES
|
||||||
CXX_INCLUDE_WHAT_YOU_USE "${_iwyu_path};${_iwyu_args}"
|
CXX_INCLUDE_WHAT_YOU_USE "${_iwyu_path};${_iwyu_args}"
|
||||||
)
|
)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
#
|
|
||||||
# set_target_iwyu([KEEP patterns...]
|
|
||||||
# [MAPPING_FILE file]
|
|
||||||
# [NO_DEFAULT_MAPPINGS]
|
|
||||||
# [PCH_IN_CODE]
|
|
||||||
# [TRANSITIVE_INCLUDES_ONLY]
|
|
||||||
# [MAX_LINE_LENGTH length]
|
|
||||||
# [NO_COMMENTS]
|
|
||||||
# [NO_FORWARD_DECLARATIONS]
|
|
||||||
# [CXX17_NAMESPACES]
|
|
||||||
# [QUOTED_INCLUDES_FIRST])
|
|
||||||
#
|
|
||||||
function(set_iwyu)
|
|
||||||
_find_iwyu()
|
|
||||||
_process_iwyu_arguments(0)
|
|
||||||
|
|
||||||
message(STATUS "Setting include-what-you-use")
|
|
||||||
message(STATUS " Path: ${_iwyu_path}")
|
|
||||||
message(STATUS " Arguments: ${_iwyu_args}")
|
|
||||||
message(STATUS "Setting include-what-you-use - done")
|
|
||||||
|
|
||||||
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "${_iwyu_path};${_iwyu_args}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
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
|
# Based on https://github.com/lefticus/cpp_starter_project/blob/master/cmake/CompilerWarnings.cmake
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.3)
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
|
||||||
option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" ON)
|
option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" ON)
|
||||||
|
|
||||||
@@ -90,8 +90,6 @@ macro(_set_flags)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
string(REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE)
|
|
||||||
set(flags ${MSVC_WARNINGS})
|
set(flags ${MSVC_WARNINGS})
|
||||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
|
elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
|
||||||
set(flags ${CLANG_WARNINGS})
|
set(flags ${CLANG_WARNINGS})
|
||||||
|
47
conanfile.py
47
conanfile.py
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
from conans import ConanFile, tools
|
from conans import ConanFile, tools
|
||||||
from conans.tools import Version, check_min_cppstd
|
from conans.tools import Version, check_min_cppstd
|
||||||
from conan.tools.cmake import CMakeToolchain, CMake, CMakeDeps
|
from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake
|
||||||
from conans.errors import ConanInvalidConfiguration
|
from conans.errors import ConanInvalidConfiguration
|
||||||
import os, re
|
import os, re
|
||||||
|
|
||||||
@@ -58,28 +58,27 @@ class UnitsConan(ConanFile):
|
|||||||
# }
|
# }
|
||||||
generators = "cmake_paths"
|
generators = "cmake_paths"
|
||||||
|
|
||||||
_cmake = None
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _run_tests(self):
|
def _run_tests(self):
|
||||||
return tools.get_env("CONAN_RUN_TESTS", False)
|
return tools.get_env("CONAN_RUN_TESTS", False)
|
||||||
|
|
||||||
def _configure_cmake(self):
|
|
||||||
if not self._cmake:
|
|
||||||
self._cmake = CMake(self)
|
|
||||||
if self._run_tests:
|
|
||||||
# developer's mode (unit tests, examples, documentation, restrictive compilation warnings, ...)
|
|
||||||
self._cmake.configure()
|
|
||||||
else:
|
|
||||||
# consumer's mode (library sources only)
|
|
||||||
self._cmake.configure(source_folder="src")
|
|
||||||
return self._cmake
|
|
||||||
|
|
||||||
def set_version(self):
|
def set_version(self):
|
||||||
content = tools.load(os.path.join(self.recipe_folder, "src/CMakeLists.txt"))
|
content = tools.load(os.path.join(self.recipe_folder, "src/CMakeLists.txt"))
|
||||||
version = re.search(r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content).group(1)
|
version = re.search(r"project\([^\)]+VERSION (\d+\.\d+\.\d+)[^\)]*\)", content).group(1)
|
||||||
self.version = version.strip()
|
self.version = version.strip()
|
||||||
|
|
||||||
|
def requirements(self):
|
||||||
|
compiler = self.settings.compiler
|
||||||
|
if compiler == "clang" and compiler.libcxx == "libc++":
|
||||||
|
self.requires("range-v3/0.11.0")
|
||||||
|
|
||||||
|
def build_requirements(self):
|
||||||
|
if self._run_tests:
|
||||||
|
self.build_requires("catch2/2.13.4")
|
||||||
|
self.build_requires("linear_algebra/0.7.1@conan-oss/stable")
|
||||||
|
if self.options.build_docs:
|
||||||
|
self.build_requires("doxygen/1.9.1")
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
compiler = self.settings.compiler
|
compiler = self.settings.compiler
|
||||||
version = Version(self.settings.compiler.version)
|
version = Version(self.settings.compiler.version)
|
||||||
@@ -102,20 +101,8 @@ class UnitsConan(ConanFile):
|
|||||||
# # build_docs has sense only in a development or CI build
|
# # build_docs has sense only in a development or CI build
|
||||||
# del self.options.build_docs
|
# del self.options.build_docs
|
||||||
|
|
||||||
def requirements(self):
|
|
||||||
compiler = self.settings.compiler
|
|
||||||
if compiler == "clang" and compiler.libcxx == "libc++":
|
|
||||||
self.requires("range-v3/0.11.0")
|
|
||||||
|
|
||||||
def build_requirements(self):
|
|
||||||
if self._run_tests:
|
|
||||||
self.build_requires("catch2/2.13.4")
|
|
||||||
self.build_requires("linear_algebra/0.7.0@public-conan/stable")
|
|
||||||
if self.options.build_docs:
|
|
||||||
self.build_requires("doxygen/1.8.20")
|
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
tc = CMakeToolchain(self)
|
tc = CMakeToolchain(self, generator=os.getenv("CONAN_CMAKE_GENERATOR"))
|
||||||
tc.variables["UNITS_DOWNCAST_MODE"] = str(self.options.downcast_mode).upper()
|
tc.variables["UNITS_DOWNCAST_MODE"] = str(self.options.downcast_mode).upper()
|
||||||
# if self._run_tests: # TODO Enable this when environment is supported in the Conan toolchain
|
# if self._run_tests: # TODO Enable this when environment is supported in the Conan toolchain
|
||||||
tc.variables["UNITS_BUILD_DOCS"] = self.options.build_docs
|
tc.variables["UNITS_BUILD_DOCS"] = self.options.build_docs
|
||||||
@@ -124,14 +111,16 @@ class UnitsConan(ConanFile):
|
|||||||
deps.generate()
|
deps.generate()
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
cmake = self._configure_cmake()
|
cmake = CMake(self)
|
||||||
|
cmake.configure(source_folder=None if self._run_tests else "src")
|
||||||
cmake.build()
|
cmake.build()
|
||||||
if self._run_tests:
|
if self._run_tests:
|
||||||
cmake.test(output_on_failure=True)
|
cmake.test(output_on_failure=True)
|
||||||
|
|
||||||
def package(self):
|
def package(self):
|
||||||
self.copy(pattern="LICENSE.md", dst="licenses")
|
self.copy(pattern="LICENSE.md", dst="licenses")
|
||||||
cmake = self._configure_cmake()
|
cmake = CMake(self)
|
||||||
|
cmake.configure(source_folder=None if self._run_tests else "src")
|
||||||
cmake.install()
|
cmake.install()
|
||||||
|
|
||||||
def package_id(self):
|
def package_id(self):
|
||||||
|
@@ -1,12 +1,19 @@
|
|||||||
# Release notes
|
# Release notes
|
||||||
|
|
||||||
- **0.7.0 WIP**
|
- **0.8.0 WIP**
|
||||||
|
- (!) fix: add `quantity_point::origin`, like `std::chrono::time_point::clock`
|
||||||
|
- fix: account for different dimensions in `quantity_point_cast`'s constraint
|
||||||
|
- build: doxygen updated to 1.9.1
|
||||||
|
- build: linear_algebra updated to 0.7.1
|
||||||
|
|
||||||
|
- **0.7.0 May 11, 2021**
|
||||||
- (!) refactor: `ScalableNumber` renamed to `Representation`
|
- (!) refactor: `ScalableNumber` renamed to `Representation`
|
||||||
- (!) refactor: output stream operators moved to the `units/quantity_io.h` header file
|
- (!) refactor: output stream operators moved to the `units/quantity_io.h` header file
|
||||||
- (!) refactor: Refactored the library file tree
|
- (!) refactor: Refactored the library file tree
|
||||||
- (!) refactor: `quantity::count()` renamed to `quantity::number()`
|
- (!) refactor: `quantity::count()` renamed to `quantity::number()`
|
||||||
- (!) refactor: `data` system renamed to `isq::iec80000` (quantity names renamed too)
|
- (!) refactor: `data` system renamed to `isq::iec80000` (quantity names renamed too)
|
||||||
- (!) refactor: quantity UDLs support has to be enabled with `UNITS_LITERALS` preprocessor define
|
- (!) refactor: `*deduced_unit` renamed to `*derived_unit`
|
||||||
|
- (!) refactor: got rid of a `noble_derived_unit`
|
||||||
- refactor: quantity (kind) point updated to reflect latest changes to `quantity`
|
- refactor: quantity (kind) point updated to reflect latest changes to `quantity`
|
||||||
- refactor: basic concepts, `quantity` and `quantity_cast` refactored
|
- refactor: basic concepts, `quantity` and `quantity_cast` refactored
|
||||||
- refactor: `abs()` definition refactored to be more explicit about the return type
|
- refactor: `abs()` definition refactored to be more explicit about the return type
|
||||||
@@ -17,12 +24,15 @@
|
|||||||
- feat: CTAD for dimensionless quantity added
|
- feat: CTAD for dimensionless quantity added
|
||||||
- feat: `modulation_rate` support added (thanks [@go2sh](https://github.com/go2sh))
|
- feat: `modulation_rate` support added (thanks [@go2sh](https://github.com/go2sh))
|
||||||
- feat: SI prefixes for `isq::iec80000` support added (thanks [@go2sh](https://github.com/go2sh))
|
- feat: SI prefixes for `isq::iec80000` support added (thanks [@go2sh](https://github.com/go2sh))
|
||||||
|
- feat: a possibility to disable quantity UDLs support with `UNITS_NO_LITERALS` preprocessor define
|
||||||
|
- feat: a support to define ISQ derived dimensions in terms of different number or order of components
|
||||||
- perf: preconditions check do not influence the runtime performance of a Release build
|
- perf: preconditions check do not influence the runtime performance of a Release build
|
||||||
- perf: `quantity_cast()` generates less assembly instructions
|
- perf: `quantity_cast()` generates less assembly instructions
|
||||||
- perf: temporary string creation removed from `quantity::op<<()`
|
- perf: temporary string creation removed from `quantity::op<<()`
|
||||||
- perf: value initialization for quantity value removed (left with a default initialization)
|
- perf: value initialization for quantity value removed (left with a default initialization)
|
||||||
- perf: limited the `equivalent` trait usage
|
- perf: limited the `equivalent` trait usage
|
||||||
- perf: limited the C++ Standard Library headers usage
|
- perf: limited the C++ Standard Library headers usage
|
||||||
|
- perf: rvalue references support added for constructors and getters
|
||||||
- (!) fix: `exp()` has sense only for dimensionless quantities
|
- (!) fix: `exp()` has sense only for dimensionless quantities
|
||||||
- (!) fix: `dim_torque` now properly divides by an angle (instead of multiply) + default unit name change
|
- (!) fix: `dim_torque` now properly divides by an angle (instead of multiply) + default unit name change
|
||||||
- fix: quantity's operators fixed to behave like the underlying types do
|
- fix: quantity's operators fixed to behave like the underlying types do
|
||||||
@@ -30,7 +40,10 @@
|
|||||||
- fix: ambiguous case for empty type list resolved
|
- fix: ambiguous case for empty type list resolved
|
||||||
- fix: downcasting facility for non-default-constructible types
|
- fix: downcasting facility for non-default-constructible types
|
||||||
- fix: restore user-warnings within the library implementation
|
- fix: restore user-warnings within the library implementation
|
||||||
|
- fix: the text symbol of `foot_pound_force` and `foot_pound_force_per_second`
|
||||||
|
- fix: quantity modulo arithmetics fixed
|
||||||
- (!) build: Conan testing version is now hosted on [Artifactory](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units)
|
- (!) build: Conan testing version is now hosted on [Artifactory](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units)
|
||||||
|
- (!) build: Linear Algebra is now hosted on its [Artifactory](https://twonington.jfrog.io/artifactory/api/conan/conan-oss)
|
||||||
- (!) build: `BUILD_DOCS` CMake option renamed to `UNITS_BUILD_DOCS`
|
- (!) build: `BUILD_DOCS` CMake option renamed to `UNITS_BUILD_DOCS`
|
||||||
- build: doxygen updated to 1.8.20
|
- build: doxygen updated to 1.8.20
|
||||||
- build: catch2 updated to 2.13.4
|
- build: catch2 updated to 2.13.4
|
||||||
@@ -39,6 +52,7 @@
|
|||||||
- build: Conan generator switched to `cmake_find_package_multi`
|
- build: Conan generator switched to `cmake_find_package_multi`
|
||||||
- build: Conan CMakeToolchain support added
|
- build: Conan CMakeToolchain support added
|
||||||
- build: CMake scripts cleanup
|
- build: CMake scripts cleanup
|
||||||
|
- build: ccache support added
|
||||||
- ci: CI switched from Travis CI to GitHub Actions
|
- ci: CI switched from Travis CI to GitHub Actions
|
||||||
|
|
||||||
- **0.6.0 September 13, 2020**
|
- **0.6.0 September 13, 2020**
|
||||||
|
@@ -91,15 +91,3 @@ WARN_AS_ERROR = NO
|
|||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
QUIET = YES
|
QUIET = YES
|
||||||
|
|
||||||
# The PREDEFINED tag can be used to specify one or more macro names that are
|
|
||||||
# defined before the preprocessor is started (similar to the -D option of e.g.
|
|
||||||
# gcc). The argument of the tag is a list of macros of the form: name or
|
|
||||||
# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
|
|
||||||
# is assumed. To prevent a macro definition from being undefined via #undef or
|
|
||||||
# recursively expanded use the := operator instead of the = operator.
|
|
||||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
|
||||||
|
|
||||||
PREDEFINED = UNITS_REFERENCES \
|
|
||||||
UNITS_LITERALS \
|
|
||||||
UNITS_ALIASES
|
|
||||||
|
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
|
avg_speed
|
||||||
=========
|
=========
|
||||||
|
|
||||||
.. literalinclude:: ../../example/references/avg_speed.cpp
|
.. literalinclude:: ../../../example/references/avg_speed.cpp
|
||||||
:caption: avg_speed.cpp
|
:caption: avg_speed.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
box_example
|
box_example
|
||||||
===========
|
===========
|
||||||
|
|
||||||
.. literalinclude:: ../../example/references/box_example.cpp
|
.. literalinclude:: ../../../example/references/box_example.cpp
|
||||||
:caption: box_example.cpp
|
:caption: box_example.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
capacitor_time_curve
|
capacitor_time_curve
|
||||||
====================
|
====================
|
||||||
|
|
||||||
.. literalinclude:: ../../example/references/capacitor_time_curve.cpp
|
.. literalinclude:: ../../../example/references/capacitor_time_curve.cpp
|
||||||
:caption: capacitor_time_curve.cpp
|
:caption: capacitor_time_curve.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
clcpp_response
|
clcpp_response
|
||||||
==============
|
==============
|
||||||
|
|
||||||
.. literalinclude:: ../../example/references/clcpp_response.cpp
|
.. literalinclude:: ../../../example/references/clcpp_response.cpp
|
||||||
:caption: clcpp_response.cpp
|
:caption: clcpp_response.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
experimental_angle
|
experimental_angle
|
||||||
==================
|
==================
|
||||||
|
|
||||||
.. literalinclude:: ../../example/references/experimental_angle.cpp
|
.. literalinclude:: ../../../example/references/experimental_angle.cpp
|
||||||
:caption: experimental_angle.cpp
|
:caption: experimental_angle.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
foot_pound_second
|
foot_pound_second
|
||||||
=================
|
=================
|
||||||
|
|
||||||
.. literalinclude:: ../../example/references/foot_pound_second.cpp
|
.. literalinclude:: ../../../example/references/foot_pound_second.cpp
|
||||||
:caption: foot_pound_second.cpp
|
:caption: foot_pound_second.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@@ -13,7 +13,7 @@ This example presents the usage of:
|
|||||||
- quantities text output formatting,
|
- quantities text output formatting,
|
||||||
- cooperation with `std::chrono`.
|
- cooperation with `std::chrono`.
|
||||||
|
|
||||||
.. literalinclude:: ../../example/glide_computer/include/glide_computer.h
|
.. literalinclude:: ../../../example/glide_computer/include/glide_computer.h
|
||||||
:caption: glide_computer.h
|
:caption: glide_computer.h
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:end-before: using namespace units;
|
:end-before: using namespace units;
|
||||||
@@ -35,7 +35,7 @@ For example we have 3 for a quantity of length:
|
|||||||
- ``height`` - a relative altitude difference between 2 points in the air
|
- ``height`` - a relative altitude difference between 2 points in the air
|
||||||
- ``altitude`` - an absolute altitude value measured form the mean sea level (AMSL).
|
- ``altitude`` - an absolute altitude value measured form the mean sea level (AMSL).
|
||||||
|
|
||||||
.. literalinclude:: ../../example/glide_computer/include/glide_computer.h
|
.. literalinclude:: ../../../example/glide_computer/include/glide_computer.h
|
||||||
:caption: glide_computer.h
|
:caption: glide_computer.h
|
||||||
:start-at: using namespace units;
|
:start-at: using namespace units;
|
||||||
:end-before: // text output
|
:end-before: // text output
|
||||||
@@ -44,7 +44,7 @@ For example we have 3 for a quantity of length:
|
|||||||
|
|
||||||
Next a custom text output is provided both for C++ output streams and the text formatting facility.
|
Next a custom text output is provided both for C++ output streams and the text formatting facility.
|
||||||
|
|
||||||
.. literalinclude:: ../../example/glide_computer/include/glide_computer.h
|
.. literalinclude:: ../../../example/glide_computer/include/glide_computer.h
|
||||||
:caption: glide_computer.h
|
:caption: glide_computer.h
|
||||||
:start-at: // text output
|
:start-at: // text output
|
||||||
:end-before: // definition of glide computer databases and utilities
|
:end-before: // definition of glide computer databases and utilities
|
||||||
@@ -58,13 +58,13 @@ convert it to the one required by the engine interface.
|
|||||||
The glide calculator takes task created as a list of waypoints, glider performance data, weather conditions,
|
The glide calculator takes task created as a list of waypoints, glider performance data, weather conditions,
|
||||||
safety constraints, and a towing height.
|
safety constraints, and a towing height.
|
||||||
|
|
||||||
.. literalinclude:: ../../example/glide_computer/include/glide_computer.h
|
.. literalinclude:: ../../../example/glide_computer/include/glide_computer.h
|
||||||
:caption: glide_computer.h
|
:caption: glide_computer.h
|
||||||
:start-at: // definition of glide computer databases and utilities
|
:start-at: // definition of glide computer databases and utilities
|
||||||
:linenos:
|
:linenos:
|
||||||
:lineno-match:
|
:lineno-match:
|
||||||
|
|
||||||
.. literalinclude:: ../../example/references/glide_computer_example.cpp
|
.. literalinclude:: ../../../example/references/glide_computer_example.cpp
|
||||||
:caption: glide_computer_example.cpp
|
:caption: glide_computer_example.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
@@ -74,7 +74,7 @@ Having all of that it estimates the number of flight phases (towing, circling, g
|
|||||||
needed to finish a task. As an output it provides the duration needed to finish the task while
|
needed to finish a task. As an output it provides the duration needed to finish the task while
|
||||||
flying a selected glider in the specific weather conditions.
|
flying a selected glider in the specific weather conditions.
|
||||||
|
|
||||||
.. literalinclude:: ../../example/glide_computer/glide_computer.cpp
|
.. literalinclude:: ../../../example/glide_computer/glide_computer.cpp
|
||||||
:caption: glide_computer.cpp
|
:caption: glide_computer.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
hello_units
|
hello_units
|
||||||
===========
|
===========
|
||||||
|
|
||||||
.. literalinclude:: ../../example/hello_units.cpp
|
.. literalinclude:: ../../../example/hello_units.cpp
|
||||||
:caption: hello_units.cpp
|
:caption: hello_units.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
total_energy
|
total_energy
|
||||||
============
|
============
|
||||||
|
|
||||||
.. literalinclude:: ../../example/references/total_energy.cpp
|
.. literalinclude:: ../../../example/references/total_energy.cpp
|
||||||
:caption: total_energy.cpp
|
:caption: total_energy.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
unknown_dimension
|
unknown_dimension
|
||||||
=================
|
=================
|
||||||
|
|
||||||
.. literalinclude:: ../../example/references/unknown_dimension.cpp
|
.. literalinclude:: ../../../example/references/unknown_dimension.cpp
|
||||||
:caption: unknown_dimension.cpp
|
:caption: unknown_dimension.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
linear_algebra
|
linear_algebra
|
||||||
==============
|
==============
|
||||||
|
|
||||||
.. literalinclude:: ../../example/references/linear_algebra.cpp
|
.. literalinclude:: ../../../example/references/linear_algebra.cpp
|
||||||
:caption: linear_algebra.cpp
|
:caption: linear_algebra.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
measurement
|
measurement
|
||||||
===========
|
===========
|
||||||
|
|
||||||
.. literalinclude:: ../../example/measurement.cpp
|
.. literalinclude:: ../../../example/measurement.cpp
|
||||||
:caption: measurement.cpp
|
:caption: measurement.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
custom_systems
|
custom_systems
|
||||||
==============
|
==============
|
||||||
|
|
||||||
.. literalinclude:: ../../example/custom_systems.cpp
|
.. literalinclude:: ../../../example/custom_systems.cpp
|
||||||
:caption: custom_systems.cpp
|
:caption: custom_systems.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
conversion_factor
|
conversion_factor
|
||||||
=================
|
=================
|
||||||
|
|
||||||
.. literalinclude:: ../../example/conversion_factor.cpp
|
.. literalinclude:: ../../../example/conversion_factor.cpp
|
||||||
:caption: conversion_factor.cpp
|
:caption: conversion_factor.cpp
|
||||||
:start-at: #include
|
:start-at: #include
|
||||||
:linenos:
|
:linenos:
|
||||||
|
@@ -23,7 +23,7 @@ The most important concepts in the library are `Unit`, `Dimension`,
|
|||||||
]
|
]
|
||||||
|
|
||||||
[<abstract>QuantityPoint|
|
[<abstract>QuantityPoint|
|
||||||
[quantity_point<Dimension, Unit, Rep>]
|
[quantity_point<PointOrigin, Unit, Rep>]
|
||||||
]
|
]
|
||||||
|
|
||||||
[<abstract>QuantityKind|
|
[<abstract>QuantityKind|
|
||||||
@@ -39,6 +39,10 @@ The most important concepts in the library are `Unit`, `Dimension`,
|
|||||||
[Unit]<-[Quantity]
|
[Unit]<-[Quantity]
|
||||||
[Quantity]<-[QuantityPoint]
|
[Quantity]<-[QuantityPoint]
|
||||||
|
|
||||||
|
[<abstract>PointOrigin]<-[QuantityPoint]
|
||||||
|
[Dimension]<-[PointOrigin]
|
||||||
|
[PointOrigin]<-[PointKind]
|
||||||
|
|
||||||
[<abstract>Kind]<-[QuantityKind]
|
[<abstract>Kind]<-[QuantityKind]
|
||||||
[Dimension]<-[Kind]
|
[Dimension]<-[Kind]
|
||||||
[Quantity]<-[QuantityKind]
|
[Quantity]<-[QuantityKind]
|
||||||
@@ -60,7 +64,7 @@ derived dimensions. Examples: ``si::dim_time``, ``si::dim_length``, ``si::dim_sp
|
|||||||
specific representation. Examples: ``quantity<si::dim_time, si::second, int>``,
|
specific representation. Examples: ``quantity<si::dim_time, si::second, int>``,
|
||||||
``si::length<si::metre, int>``, ``si::speed<si::kilometre_per_hour>``.
|
``si::length<si::metre, int>``, ``si::speed<si::kilometre_per_hour>``.
|
||||||
|
|
||||||
`QuantityPoint` is an absolute `Quantity` with respect to some origin.
|
`QuantityPoint` is an absolute `Quantity` with respect to an origin.
|
||||||
Examples: timestamp (as opposed to duration), absolute temperature
|
Examples: timestamp (as opposed to duration), absolute temperature
|
||||||
(as opposed to temperature difference).
|
(as opposed to temperature difference).
|
||||||
|
|
||||||
@@ -68,6 +72,6 @@ Examples: timestamp (as opposed to duration), absolute temperature
|
|||||||
distance (``horizonal_kind``) and height (``vertical_kind``) are different kinds
|
distance (``horizonal_kind``) and height (``vertical_kind``) are different kinds
|
||||||
of a length quantity.
|
of a length quantity.
|
||||||
|
|
||||||
`QuantityPointKind` is an absolute `QuantityKind` with respect to some origin.
|
`QuantityPointKind` is an absolute `QuantityKind` with respect to an origin.
|
||||||
Examples: altitude is a quantity point of ``vertical_kind`` (as opposed to
|
Examples: altitude is a quantity point of ``vertical_kind`` (as opposed to
|
||||||
height).
|
height).
|
||||||
|
@@ -77,7 +77,7 @@ you can use a quantity argument instead of a quantity kind.
|
|||||||
:emphasize-lines: 8-9
|
:emphasize-lines: 8-9
|
||||||
|
|
||||||
struct height_kind : kind<height_kind, dim_length> {};
|
struct height_kind : kind<height_kind, dim_length> {};
|
||||||
struct rate_of_climb_kind : derived_kind<rate_of_climb_kind, height_kind, dim_speed> {};
|
struct rate_of_climb_kind : derived_kind<rate_of_climb_kind, dim_speed, height_kind> {};
|
||||||
|
|
||||||
template <Unit U, Representation Rep = double> using height = quantity_kind<height_kind, U, Rep>;
|
template <Unit U, Representation Rep = double> using height = quantity_kind<height_kind, U, Rep>;
|
||||||
template <Unit U, Representation Rep = double> using rate_of_climb = quantity_kind<rate_of_climb_kind, U, Rep>;
|
template <Unit U, Representation Rep = double> using rate_of_climb = quantity_kind<rate_of_climb_kind, U, Rep>;
|
||||||
@@ -90,7 +90,7 @@ you can use a quantity argument instead of a quantity kind.
|
|||||||
:emphasize-lines: 8-12
|
:emphasize-lines: 8-12
|
||||||
|
|
||||||
struct width_kind : kind<width_kind, dim_length> {};
|
struct width_kind : kind<width_kind, dim_length> {};
|
||||||
struct horizontal_area_kind : derived_kind<horizontal_area_kind, width_kind, dim_area> {};
|
struct horizontal_area_kind : derived_kind<horizontal_area_kind, dim_area, width_kind> {};
|
||||||
|
|
||||||
template <Unit U, Representation Rep = double> using width = quantity_kind<width_kind, U, Rep>;
|
template <Unit U, Representation Rep = double> using width = quantity_kind<width_kind, U, Rep>;
|
||||||
template <Unit U, Representation Rep = double> using horizontal_area = quantity_kind<horizontal_area_kind, U, Rep>;
|
template <Unit U, Representation Rep = double> using horizontal_area = quantity_kind<horizontal_area_kind, U, Rep>;
|
||||||
@@ -106,8 +106,9 @@ Quantity Points
|
|||||||
+++++++++++++++
|
+++++++++++++++
|
||||||
|
|
||||||
Quantity points have a more restricted set of operations.
|
Quantity points have a more restricted set of operations.
|
||||||
Quantity can be added to or subtracted from a quantity point.
|
Quantity can be added to or subtracted
|
||||||
The result will always be a quantity point of the same dimension:
|
from a quantity point of the same origin.
|
||||||
|
The result will always be a quantity point of the same origin:
|
||||||
|
|
||||||
.. code-block::
|
.. code-block::
|
||||||
:emphasize-lines: 3-5
|
:emphasize-lines: 3-5
|
||||||
@@ -132,9 +133,10 @@ The result is a relative quantity of the same dimension:
|
|||||||
|
|
||||||
It is not allowed to:
|
It is not allowed to:
|
||||||
|
|
||||||
- add quantity points
|
- add quantity points,
|
||||||
- subtract a quantity point from a quantity:
|
- subtract a quantity point from a quantity,
|
||||||
- multiply nor divide quantity points with anything else.
|
- multiply nor divide quantity points with anything else, and
|
||||||
|
- mix quantity points with different origins:
|
||||||
|
|
||||||
.. code-block::
|
.. code-block::
|
||||||
:emphasize-lines: 3-5
|
:emphasize-lines: 3-5
|
||||||
@@ -144,6 +146,8 @@ The result is a relative quantity of the same dimension:
|
|||||||
auto res1 = quantity_point{dist1} + quantity_point{dist2}; // ERROR
|
auto res1 = quantity_point{dist1} + quantity_point{dist2}; // ERROR
|
||||||
auto res2 = dist1 - quantity_point{dist2}; // ERROR
|
auto res2 = dist1 - quantity_point{dist2}; // ERROR
|
||||||
auto res3 = quantity_point{dist1} / (2 * s); // ERROR
|
auto res3 = quantity_point{dist1} / (2 * s); // ERROR
|
||||||
|
auto res4 = quantity_point{std::chrono::utc_second{1s}} +
|
||||||
|
quantity_point{std::chrono::sys_second{1s}}; // ERROR
|
||||||
|
|
||||||
Quantity Point Kinds
|
Quantity Point Kinds
|
||||||
++++++++++++++++++++
|
++++++++++++++++++++
|
||||||
|
@@ -70,7 +70,7 @@ Unit-Specific Aliases (Experimental)
|
|||||||
Additionally to the dimension-specific aliases there are also ones provided for
|
Additionally to the dimension-specific aliases there are also ones provided for
|
||||||
each and every :term:`unit` in the library::
|
each and every :term:`unit` in the library::
|
||||||
|
|
||||||
#ifdef UNITS_ALIASES
|
#ifndef UNITS_NO_ALIASES
|
||||||
|
|
||||||
namespace units::aliases::isq::si::inline length {
|
namespace units::aliases::isq::si::inline length {
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ each and every :term:`unit` in the library::
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // UNITS_ALIASES
|
#endif // UNITS_NO_ALIASES
|
||||||
|
|
||||||
Using the above our code can look as follows::
|
Using the above our code can look as follows::
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ Quantity References (Experimental)
|
|||||||
Quantity References provide an alternative and simplified way to create quantities.
|
Quantity References provide an alternative and simplified way to create quantities.
|
||||||
They are defined using the `reference` class template::
|
They are defined using the `reference` class template::
|
||||||
|
|
||||||
#ifdef UNITS_REFERENCES
|
#ifndef UNITS_NO_REFERENCES
|
||||||
|
|
||||||
namespace length_references {
|
namespace length_references {
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ They are defined using the `reference` class template::
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
#endif // UNITS_REFERENCES
|
#endif // UNITS_NO_REFERENCES
|
||||||
|
|
||||||
With the above our code can look as follows::
|
With the above our code can look as follows::
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@ User Defined Literals (Experimental)
|
|||||||
Alternatively, to construct quantities with compile-time known values the library provides
|
Alternatively, to construct quantities with compile-time known values the library provides
|
||||||
:abbr:`UDL (User Defined Literal)` s for each :term:`unit` of every :term:`dimension`::
|
:abbr:`UDL (User Defined Literal)` s for each :term:`unit` of every :term:`dimension`::
|
||||||
|
|
||||||
#ifdef UNITS_LITERALS
|
#ifndef UNITS_NO_LITERALS
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ Alternatively, to construct quantities with compile-time known values the librar
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_NO_LITERALS
|
||||||
|
|
||||||
Thanks to them the same code can be as simple as::
|
Thanks to them the same code can be as simple as::
|
||||||
|
|
||||||
@@ -186,13 +186,6 @@ Thanks to them the same code can be as simple as::
|
|||||||
``d`` (day), ``l`` or ``L`` (litre), ``erg``, ``ergps``). This is why the
|
``d`` (day), ``l`` or ``L`` (litre), ``erg``, ``ergps``). This is why the
|
||||||
``_q_`` prefix was consistently applied to all the UDLs.
|
``_q_`` prefix was consistently applied to all the UDLs.
|
||||||
|
|
||||||
.. important::
|
|
||||||
|
|
||||||
As one can read in the next section UDLs, are considered to be inferior to `Quantity References`_
|
|
||||||
and their definition affects compile-time performance a lot. This is why they are an opt-in feature
|
|
||||||
of the library and in order to use them one has to provide a `UNITS_LITERALS` preprocessor definition.
|
|
||||||
|
|
||||||
|
|
||||||
UDLs vs Quantity References
|
UDLs vs Quantity References
|
||||||
+++++++++++++++++++++++++++
|
+++++++++++++++++++++++++++
|
||||||
|
|
||||||
@@ -473,6 +466,19 @@ Summary
|
|||||||
+-----------------------------------------------+-------------+------------+---------------+
|
+-----------------------------------------------+-------------+------------+---------------+
|
||||||
|
|
||||||
|
|
||||||
|
Don't pay for what you don't use (compile-time performance)
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
As noted in the previous chapter, each quantity creation helper has a different impact on the compile-time
|
||||||
|
performance. Aliases tend to be the fastest to compile but even their definition can be expensive for some
|
||||||
|
if it is not used in the source code. This is why it is possible to opt-out from each or every quantity
|
||||||
|
creation helper with the following preprocessor defines::
|
||||||
|
|
||||||
|
#define UNITS_NO_ALIASES
|
||||||
|
#define UNITS_NO_REFERENCES
|
||||||
|
#define UNITS_NO_LITERALS
|
||||||
|
|
||||||
|
|
||||||
Dimension-specific Concepts
|
Dimension-specific Concepts
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
@@ -3,9 +3,20 @@
|
|||||||
Quantity Points
|
Quantity Points
|
||||||
===============
|
===============
|
||||||
|
|
||||||
A quantity point is an absolute quantity with respect to zero
|
A quantity point is an absolute quantity with respect to an origin
|
||||||
(which represents some origin) and is represented in the library with a
|
and is represented in the library with a `quantity_point` class template.
|
||||||
`quantity_point` class template.
|
|
||||||
|
Point Origins
|
||||||
|
-------------
|
||||||
|
|
||||||
|
We need a `point_origin` to represent the origin of a quantity point::
|
||||||
|
|
||||||
|
struct mean_sea_level : point_origin<si::dim_length> {};
|
||||||
|
|
||||||
|
Quantities points with this origin represent a point from the mean sea level.
|
||||||
|
|
||||||
|
The library offers a `dynamic_origin<Dimension>`
|
||||||
|
for quantity points whose origin is not specified in the type system.
|
||||||
|
|
||||||
|
|
||||||
Construction
|
Construction
|
||||||
@@ -14,7 +25,7 @@ Construction
|
|||||||
To create the quantity point object from a `quantity` we just have to pass
|
To create the quantity point object from a `quantity` we just have to pass
|
||||||
the value to the `quantity_point` class template explicit constructor::
|
the value to the `quantity_point` class template explicit constructor::
|
||||||
|
|
||||||
quantity_point<si::dim_length, si::kilometre, double> d(123 * km);
|
quantity_point<dynamic_origin<si::dim_length>, si::kilometre, double> d(123 * km);
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
@@ -25,7 +36,7 @@ the value to the `quantity_point` class template explicit constructor::
|
|||||||
`copy initialization <https://en.cppreference.com/w/cpp/language/copy_initialization>`_
|
`copy initialization <https://en.cppreference.com/w/cpp/language/copy_initialization>`_
|
||||||
**does not compile**::
|
**does not compile**::
|
||||||
|
|
||||||
quantity_point<si::dim_length, si::kilometre, double> d = 123 * km; // ERROR
|
quantity_point<dynamic_origin<si::dim_length>, si::kilometre, double> d = 123 * km; // ERROR
|
||||||
|
|
||||||
|
|
||||||
Differences To Quantity
|
Differences To Quantity
|
||||||
|
@@ -8,7 +8,7 @@ compare quantities of the same dimension a notion of a :term:`measurement unit`
|
|||||||
was introduced. Units are designated by conventionally assigned names and
|
was introduced. Units are designated by conventionally assigned names and
|
||||||
symbols. Thanks to them it is possible to compare two quantities of the
|
symbols. Thanks to them it is possible to compare two quantities of the
|
||||||
same dimension and express the ratio of the second quantity to the first
|
same dimension and express the ratio of the second quantity to the first
|
||||||
one as a number. For example ``10s`` is ``10`` times more than ``1s``.
|
one as a number. For example ``10 s`` is ``10`` times more than ``1 s``.
|
||||||
|
|
||||||
Base quantities are expressed in terms of :term:`base units <base unit>`
|
Base quantities are expressed in terms of :term:`base units <base unit>`
|
||||||
(i.e. ``m`` (meter), ``s`` (second)), while derived quantities are expressed
|
(i.e. ``m`` (meter), ``s`` (second)), while derived quantities are expressed
|
||||||
@@ -94,97 +94,14 @@ knows how to convert ``si::metre`` to ``si::centimetre`` and vice versa).
|
|||||||
:ref:`use_cases/extensions:Custom Systems` chapter.
|
:ref:`use_cases/extensions:Custom Systems` chapter.
|
||||||
|
|
||||||
|
|
||||||
Derived Units
|
|
||||||
-------------
|
|
||||||
|
|
||||||
Derived units can be either named or unnamed.
|
|
||||||
|
|
||||||
Derived Named Units
|
|
||||||
^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Derived named units have a unique symbol (i.e. ``N`` (newton) or ``Pa``
|
|
||||||
(pascal)) and they are defined in the same way as base units (which
|
|
||||||
always have to be a named unit)::
|
|
||||||
|
|
||||||
namespace si {
|
|
||||||
|
|
||||||
struct newton : named_unit<newton, "N", prefix> {};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Derived Unnamed Units
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Derived unnamed units are the units where the symbol is derived from the
|
|
||||||
base quantities symbols and the expression of the dependence of the derived
|
|
||||||
quantity on the base quantities (i.e. ``m/s`` (metre per second), ``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
|
Scaled Units
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Until now we talked mostly about
|
Described above base units (in case of base quantities) and
|
||||||
:term:`coherent units <coherent derived unit>` which are units used to
|
:term:`coherent units <coherent derived unit>` (in case of derived quantities),
|
||||||
define dimensions and thus, in their system of units, have proportionality
|
in their system of units, have proportionality factor/ratio equal to one.
|
||||||
factor/ratio equals one. However quantities of each dimension can also use
|
However, quantities of such dimensions can also use units of measurement
|
||||||
other units of measurement to describe their magnitude (numerical value).
|
with other ratios to describe their magnitude (numerical value).
|
||||||
|
|
||||||
|
|
||||||
Named Scaled Units
|
Named Scaled Units
|
||||||
@@ -289,13 +206,99 @@ example we can define ``si::kilometre`` as::
|
|||||||
as ``km²`` would be invalid).
|
as ``km²`` would be invalid).
|
||||||
|
|
||||||
|
|
||||||
Deduced Units
|
Derived Units
|
||||||
^^^^^^^^^^^^^
|
-------------
|
||||||
|
|
||||||
|
:term:`Derived units <derived unit>` are the units used to measure
|
||||||
|
:term:`derived quantities <derived quantity>`. They can either have their own unique
|
||||||
|
names (i.e. ``N`` (newton)) or can be composed from the names of units of quantities
|
||||||
|
used to define thier derived quantity (i.e. ``km/h``).
|
||||||
|
|
||||||
|
|
||||||
|
Derived Named Units
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Derived named units have a unique symbol (i.e. ``N`` (newton) or ``Pa``
|
||||||
|
(pascal)) and they are defined in the same way as base units (which
|
||||||
|
always have to be a named unit)::
|
||||||
|
|
||||||
|
namespace si {
|
||||||
|
|
||||||
|
struct newton : named_unit<newton, "N", prefix> {};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Derived Unnamed Units
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Derived unnamed units are the units where the symbol is derived from the
|
||||||
|
base quantities symbols and the expression of the dependence of the derived
|
||||||
|
quantity on the base quantities (i.e. ``m/s`` (metre per second), ``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,
|
For some units determining of a correct scaling ratio may not be trivial,
|
||||||
and even if done correctly, may be a pain to maintain. For a simple example
|
and even if done correctly, may be a pain to maintain. For a simple example
|
||||||
let's take a "kilometre per hour" unit. What is the easiest to maintain
|
let's take a "kilometre per hour" unit. What is the easiest to maintain
|
||||||
ratio in reference to "metre per second":
|
ratio in reference to the "metre per second":
|
||||||
|
|
||||||
- ``1000/3600``
|
- ``1000/3600``
|
||||||
- ``10/36``
|
- ``10/36``
|
||||||
@@ -303,30 +306,27 @@ ratio in reference to "metre per second":
|
|||||||
|
|
||||||
Whichever, we choose there will always be someone not happy with our choice.
|
Whichever, we choose there will always be someone not happy with our choice.
|
||||||
|
|
||||||
Thanks to a `deduced_unit` class template provided by the library this problem
|
Thanks to a `derived_unit` class template provided by the library this problem
|
||||||
does not exist at all. With it ``si::kilometre_per_hour`` can be defined as::
|
does not exist at all. With it ``si::kilometre_per_hour`` can be defined as::
|
||||||
|
|
||||||
namespace si {
|
namespace si {
|
||||||
|
|
||||||
struct kilometre_per_hour : deduced_unit<kilometre_per_hour, dim_speed, kilometre, hour> {};
|
struct kilometre_per_hour : derived_unit<kilometre_per_hour, dim_speed, kilometre, hour> {};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
In case the deduced unit should served as a named one we can use ether a
|
In case the scaled derived unit should serve as a named one we can use
|
||||||
`named_deduced_unit` where the user is able to provide a symbol for the unit
|
a `named_derived_unit` where the user is able to provide a symbol for the unit
|
||||||
by him/her-self or `noble_deduced_unit` where the symbol is the deduced name
|
by him/her-self::
|
||||||
based on the ingredients::
|
|
||||||
|
|
||||||
namespace si::fps {
|
namespace si::fps {
|
||||||
|
|
||||||
struct nautical_mile_per_hour : named_deduced_unit<nautical_mile_per_hour, dim_speed,
|
struct knot : named_derived_unit<knot, dim_speed, "knot", no_prefix, nautical_mile, hour> {};
|
||||||
"knot", no_prefix, nautical_mile, hour>{};
|
|
||||||
struct foot_pound_force : noble_deduced_unit<foot_pound_force, dim_energy, pound_force, foot> {};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Please note that deduced units are the only unit-related class template that
|
Please note that the dervided scaled units are the only unit-related class templates
|
||||||
take a dimension as its parameter. This derived dimension provides a :term:`recipe`
|
that take a dimension as its parameter. This derived dimension provides a :term:`recipe`
|
||||||
used for its definition. Based on the information stored in the recipe
|
used for its definition. Based on the information stored in the recipe
|
||||||
(order, type, and exponents of composite dimensions) and the ratios of units
|
(order, type, and exponents of composite dimensions) and the ratios of units
|
||||||
provided in the template parameter list after the derived dimension parameter,
|
provided in the template parameter list after the derived dimension parameter,
|
||||||
@@ -377,9 +377,8 @@ of a `scaled_unit` class template:
|
|||||||
[scaled_unit<UnitRatio, Unit>]<:-[named_unit<Child, Symbol, PrefixFamily>]
|
[scaled_unit<UnitRatio, Unit>]<:-[named_unit<Child, Symbol, PrefixFamily>]
|
||||||
[scaled_unit<UnitRatio, Unit>]<:-[named_scaled_unit<Child, Symbol, PrefixFamily, Ratio, Unit>]
|
[scaled_unit<UnitRatio, Unit>]<:-[named_scaled_unit<Child, Symbol, PrefixFamily, Ratio, Unit>]
|
||||||
[scaled_unit<UnitRatio, Unit>]<:-[prefixed_unit<Child, Prefix, Unit>]
|
[scaled_unit<UnitRatio, Unit>]<:-[prefixed_unit<Child, Prefix, Unit>]
|
||||||
[scaled_unit<UnitRatio, Unit>]<:-[deduced_unit<Child, Dimension, Unit, Unit...>]
|
[scaled_unit<UnitRatio, Unit>]<:-[derived_unit<Child, Dimension, Unit, Unit...>]
|
||||||
[scaled_unit<UnitRatio, Unit>]<:-[noble_deduced_unit<Child, Dimension, Unit, Unit...>]
|
[scaled_unit<UnitRatio, Unit>]<:-[named_derived_unit<Child, Dimension, Symbol, PrefixFamily, Unit, Unit...>]
|
||||||
[scaled_unit<UnitRatio, Unit>]<:-[named_deduced_unit<Child, Dimension, Symbol, PrefixFamily, Unit, Unit...>]
|
|
||||||
[scaled_unit<UnitRatio, Unit>]<:-[alias_unit<Unit, Symbol, PrefixFamily>]
|
[scaled_unit<UnitRatio, Unit>]<:-[alias_unit<Unit, Symbol, PrefixFamily>]
|
||||||
[scaled_unit<UnitRatio, Unit>]<:-[prefixed_alias_unit<Unit, Prefix, AliasUnit>]
|
[scaled_unit<UnitRatio, Unit>]<:-[prefixed_alias_unit<Unit, Prefix, AliasUnit>]
|
||||||
|
|
||||||
|
@@ -3,8 +3,6 @@ Quick Start
|
|||||||
|
|
||||||
Here is a small example of possible operations::
|
Here is a small example of possible operations::
|
||||||
|
|
||||||
#define UNITS_REFERENCES
|
|
||||||
|
|
||||||
#include <units/isq/si/area.h>
|
#include <units/isq/si/area.h>
|
||||||
#include <units/isq/si/frequency.h>
|
#include <units/isq/si/frequency.h>
|
||||||
#include <units/isq/si/length.h>
|
#include <units/isq/si/length.h>
|
||||||
@@ -34,7 +32,7 @@ Here is a small example of possible operations::
|
|||||||
|
|
||||||
.. admonition:: Try it on Compiler Explorer
|
.. admonition:: Try it on Compiler Explorer
|
||||||
|
|
||||||
`Example #1 <https://godbolt.org/z/53bTahKd8>`_
|
`Example #1 <https://godbolt.org/z/5dvY8Woh1>`_
|
||||||
|
|
||||||
This library requires some C++20 features (concepts, classes as
|
This library requires some C++20 features (concepts, classes as
|
||||||
:abbr:`NTTP (Non-Type Template Parameter)`, ...). Thanks to them the user gets a powerful
|
:abbr:`NTTP (Non-Type Template Parameter)`, ...). Thanks to them the user gets a powerful
|
||||||
@@ -42,10 +40,6 @@ but still easy to use interface where all unit conversions and dimensional analy
|
|||||||
performed without sacrificing on accuracy. Please see the below example for a quick preview
|
performed without sacrificing on accuracy. Please see the below example for a quick preview
|
||||||
of basic library features::
|
of basic library features::
|
||||||
|
|
||||||
#define UNITS_ALIASES
|
|
||||||
#define UNITS_LITERALS
|
|
||||||
#define UNITS_REFERENCES
|
|
||||||
|
|
||||||
#include <units/format.h>
|
#include <units/format.h>
|
||||||
#include <units/isq/si/international/length.h>
|
#include <units/isq/si/international/length.h>
|
||||||
#include <units/isq/si/international/speed.h>
|
#include <units/isq/si/international/speed.h>
|
||||||
@@ -92,7 +86,7 @@ of basic library features::
|
|||||||
|
|
||||||
.. admonition:: Try it on Compiler Explorer
|
.. admonition:: Try it on Compiler Explorer
|
||||||
|
|
||||||
`Example #2 <https://godbolt.org/z/jKnPPPEx6>`_
|
`Example #2 <https://godbolt.org/z/9fnzfbhb6>`_
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
||||||
|
@@ -16,13 +16,10 @@ Units
|
|||||||
.. doxygenstruct:: units::prefixed_unit
|
.. doxygenstruct:: units::prefixed_unit
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. doxygenstruct:: units::deduced_unit
|
.. doxygenstruct:: units::derived_unit
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. doxygenstruct:: units::noble_deduced_unit
|
.. doxygenstruct:: units::named_derived_unit
|
||||||
:members:
|
|
||||||
|
|
||||||
.. doxygenstruct:: units::named_deduced_unit
|
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. doxygenstruct:: units::alias_unit
|
.. doxygenstruct:: units::alias_unit
|
||||||
|
@@ -92,7 +92,6 @@ in *~/.conan/profiles* directory. An example profile can look as follows:
|
|||||||
[env]
|
[env]
|
||||||
CC=/usr/bin/gcc-10
|
CC=/usr/bin/gcc-10
|
||||||
CXX=/usr/bin/g++-10
|
CXX=/usr/bin/g++-10
|
||||||
CONAN_CMAKE_GENERATOR=Ninja
|
|
||||||
|
|
||||||
.. tip::
|
.. tip::
|
||||||
|
|
||||||
@@ -248,7 +247,7 @@ library release the following steps may be performed:
|
|||||||
:caption: conanfile.txt
|
:caption: conanfile.txt
|
||||||
|
|
||||||
[requires]
|
[requires]
|
||||||
mp-units/0.6.0
|
mp-units/0.7.0
|
||||||
|
|
||||||
[generators]
|
[generators]
|
||||||
CMakeToolchain
|
CMakeToolchain
|
||||||
@@ -279,7 +278,7 @@ library release the following steps may be performed:
|
|||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
mkdir build && cd build
|
mkdir my_project/build && cd my_project/build
|
||||||
conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -b=missing
|
conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -b=missing
|
||||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
|
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
|
||||||
cmake --build .
|
cmake --build .
|
||||||
@@ -314,7 +313,7 @@ differences:
|
|||||||
:caption: conanfile.txt
|
:caption: conanfile.txt
|
||||||
|
|
||||||
[requires]
|
[requires]
|
||||||
mp-units/0.7.0@mpusz/testing
|
mp-units/0.8.0@mpusz/testing
|
||||||
|
|
||||||
[generators]
|
[generators]
|
||||||
CMakeToolchain
|
CMakeToolchain
|
||||||
@@ -330,12 +329,27 @@ differences:
|
|||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
mkdir build && cd build
|
mkdir my_project/build && cd my_project/build
|
||||||
conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -b=outdated -u
|
conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -b=outdated -u
|
||||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
|
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
|
||||||
cmake --build .
|
cmake --build .
|
||||||
|
|
||||||
|
|
||||||
|
Install
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
In case you don't want to use Conan in your project and just want to install the **mp-units**
|
||||||
|
library on your file system and use it via ``find_package(mp-units)`` from another repository
|
||||||
|
to find it, it is enough to perform the following steps:
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
mkdir units/build && cd units/build
|
||||||
|
conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -b=missing
|
||||||
|
cmake ../src -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
|
||||||
|
cmake --install . --prefix <install_dir>
|
||||||
|
|
||||||
|
|
||||||
Contributing (or just building all the tests, examples, and documentation)
|
Contributing (or just building all the tests, examples, and documentation)
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -349,10 +363,10 @@ in **mp-units** repository, you should:
|
|||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
conan remote add linear-algebra https://api.bintray.com/conan/twonington/public-conan
|
conan remote add linear-algebra https://twonington.jfrog.io/artifactory/api/conan/conan-oss
|
||||||
git clone https://github.com/mpusz/units.git && cd units
|
git clone https://github.com/mpusz/units.git && cd units
|
||||||
pip3 install -r docs/requirements.txt
|
pip3 install -r docs/requirements.txt
|
||||||
mkdir build && cd build
|
mkdir units/build && cd units/build
|
||||||
conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -e mp-units:CONAN_RUN_TESTS=True -b outdated -u
|
conan install .. -pr <your_conan_profile> -s compiler.cppstd=20 -e mp-units:CONAN_RUN_TESTS=True -b outdated -u
|
||||||
conan build ..
|
conan build ..
|
||||||
|
|
||||||
@@ -387,4 +401,4 @@ Uploading **mp-units** Package to the Conan Server
|
|||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
conan upload -r <remote-name> --all mp-units/0.7.0@<user>/<channel>
|
conan upload -r <remote-name> --all mp-units/0.8.0@<user>/<channel>
|
||||||
|
@@ -118,7 +118,7 @@ coherent unit::
|
|||||||
exponent<si::dim_area, 1>, exponent<si::dim_time, -1>> {};
|
exponent<si::dim_area, 1>, exponent<si::dim_time, -1>> {};
|
||||||
|
|
||||||
// our unit of interest for a new derived dimension
|
// our unit of interest for a new derived dimension
|
||||||
struct desk_per_hour : deduced_unit<desk_per_hour, dim_desk_rate, desk, si::hour> {};
|
struct desk_per_hour : derived_unit<desk_per_hour, dim_desk_rate, desk, si::hour> {};
|
||||||
|
|
||||||
// a quantity of our dimension
|
// a quantity of our dimension
|
||||||
template<UnitOf<dim_desk_rate> U, Representation Rep = double>
|
template<UnitOf<dim_desk_rate> U, Representation Rep = double>
|
||||||
@@ -167,7 +167,7 @@ With the above we can now define a new derived dimension::
|
|||||||
exponent<dim_people, 1>,
|
exponent<dim_people, 1>,
|
||||||
exponent<si::dim_area, -1>> {};
|
exponent<si::dim_area, -1>> {};
|
||||||
|
|
||||||
struct person_per_desk : deduced_unit<person_per_desk, dim_occupancy_rate, person, desk> {};
|
struct person_per_desk : derived_unit<person_per_desk, dim_occupancy_rate, person, desk> {};
|
||||||
|
|
||||||
template<UnitOf<dim_occupancy_rate> U, Representation Rep = double>
|
template<UnitOf<dim_occupancy_rate> U, Representation Rep = double>
|
||||||
using occupancy_rate = quantity<dim_occupancy_rate, U, Rep>;
|
using occupancy_rate = quantity<dim_occupancy_rate, U, Rep>;
|
||||||
|
@@ -56,11 +56,12 @@ such an explicit conversion::
|
|||||||
|
|
||||||
For external quantity point-like types, `quantity_point_like_traits` is also provided.
|
For external quantity point-like types, `quantity_point_like_traits` is also provided.
|
||||||
It works just like `quantity_like_traits`, except that
|
It works just like `quantity_like_traits`, except that
|
||||||
``number(T)`` is replaced with ``relative(T)`` that returns the `QuantityLike` value.
|
``number(T)`` is replaced with ``relative(T)`` that returns the `QuantityLike` value
|
||||||
|
and ``dimension`` is replaced with ``origin``.
|
||||||
|
|
||||||
Similar to `quantity` and `quantity_kind`, `quantity_point` and `quantity_kind_point`
|
Similar to `quantity` and `quantity_kind`, `quantity_point` and `quantity_kind_point`
|
||||||
provide a deduction guide from `QuantityPointLike`::
|
provide a deduction guide from `QuantityPointLike`::
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
static_assert(quantity_point{std::chrono::sys_seconds{1s}} + 1 * s == quantity_point{2s});
|
static_assert((quantity_point{std::chrono::sys_seconds{1s}} + 1 * s).relative() == 2s);
|
||||||
|
@@ -11,7 +11,7 @@ enough to be used with other Linear Algebra libraries existing on the market.
|
|||||||
All of the examples provided in this chapter refer to the official proposal of the
|
All of the examples provided in this chapter refer to the official proposal of the
|
||||||
Linear Algebra Library for the C++23 defined in `P1385 <https://wg21.link/P1385>`_
|
Linear Algebra Library for the C++23 defined in `P1385 <https://wg21.link/P1385>`_
|
||||||
and its latest implementation from `GitHub <https://github.com/BobSteagall/wg21>`_
|
and its latest implementation from `GitHub <https://github.com/BobSteagall/wg21>`_
|
||||||
or `Conan <https://bintray.com/twonington/public-conan/linear_algebra%3Apublic-conan>`_.
|
or `Conan <https://twonington.jfrog.io/artifactory/api/conan/conan-oss>`_.
|
||||||
Also, to simplify the examples all of them assume::
|
Also, to simplify the examples all of them assume::
|
||||||
|
|
||||||
using namespace std::math;
|
using namespace std::math;
|
||||||
|
@@ -28,7 +28,10 @@ cmake_minimum_required(VERSION 3.2)
|
|||||||
function(add_example target)
|
function(add_example target)
|
||||||
add_executable(${target}-aliases ${target}.cpp)
|
add_executable(${target}-aliases ${target}.cpp)
|
||||||
target_link_libraries(${target}-aliases PRIVATE ${ARGN})
|
target_link_libraries(${target}-aliases PRIVATE ${ARGN})
|
||||||
target_compile_definitions(${target}-aliases PRIVATE UNITS_ALIASES)
|
target_compile_definitions(${target}-aliases PRIVATE
|
||||||
|
UNITS_NO_LITERALS
|
||||||
|
UNITS_NO_REFERENCES
|
||||||
|
)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international)
|
add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international)
|
||||||
@@ -43,7 +46,10 @@ add_example(unknown_dimension mp-units::core-io mp-units::si)
|
|||||||
|
|
||||||
if(NOT UNITS_LIBCXX)
|
if(NOT UNITS_LIBCXX)
|
||||||
add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer)
|
add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer)
|
||||||
target_compile_definitions(glide_computer_example-aliases PRIVATE UNITS_REFERENCES)
|
target_compile_definitions(glide_computer_example-aliases PRIVATE
|
||||||
|
UNITS_NO_LITERALS
|
||||||
|
UNITS_NO_REFERENCES
|
||||||
|
)
|
||||||
|
|
||||||
find_package(linear_algebra CONFIG REQUIRED)
|
find_package(linear_algebra CONFIG REQUIRED)
|
||||||
add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si)
|
add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si)
|
||||||
|
@@ -53,8 +53,8 @@ distance spherical_distance(position from, position to)
|
|||||||
return distance(earth_radius * central_angle);
|
return distance(earth_radius * central_angle);
|
||||||
} else {
|
} else {
|
||||||
// the haversine formula
|
// the haversine formula
|
||||||
const auto sin_lat = sin(lat2 - lat1) / 2;
|
const auto sin_lat = sin((lat2 - lat1) / 2);
|
||||||
const auto sin_lon = sin(lon2 - lon1) / 2;
|
const auto sin_lon = sin((lon2 - lon1) / 2);
|
||||||
const auto central_angle = 2 * asin(sqrt(sin_lat * sin_lat + cos(lat1) * cos(lat2) * sin_lon * sin_lon));
|
const auto central_angle = 2 * asin(sqrt(sin_lat * sin_lat + cos(lat1) * cos(lat2) * sin_lon * sin_lon));
|
||||||
return distance(earth_radius * central_angle);
|
return distance(earth_radius * central_angle);
|
||||||
}
|
}
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#include <units/quantity_point_kind.h>
|
#include <units/quantity_point_kind.h>
|
||||||
// IWYU pragma: end_exports
|
// IWYU pragma: end_exports
|
||||||
|
|
||||||
|
#include <units/chrono.h>
|
||||||
#include <units/format.h>
|
#include <units/format.h>
|
||||||
#include <units/math.h> // IWYU pragma: keep
|
#include <units/math.h> // IWYU pragma: keep
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -77,8 +78,8 @@ constexpr units::Dimensionless auto operator/(const QK1& lhs, const QK2& rhs)
|
|||||||
using horizontal_kind = geographic::horizontal_kind;
|
using horizontal_kind = geographic::horizontal_kind;
|
||||||
struct vertical_kind : units::kind<vertical_kind, units::isq::si::dim_length> {};
|
struct vertical_kind : units::kind<vertical_kind, units::isq::si::dim_length> {};
|
||||||
struct vertical_point_kind : units::point_kind<vertical_point_kind, vertical_kind> {};
|
struct vertical_point_kind : units::point_kind<vertical_point_kind, vertical_kind> {};
|
||||||
struct velocity_kind : units::derived_kind<velocity_kind, horizontal_kind, units::isq::si::dim_speed> {};
|
struct velocity_kind : units::derived_kind<velocity_kind, units::isq::si::dim_speed, horizontal_kind> {};
|
||||||
struct rate_of_climb_kind : units::derived_kind<rate_of_climb_kind, vertical_kind, units::isq::si::dim_speed> {};
|
struct rate_of_climb_kind : units::derived_kind<rate_of_climb_kind, units::isq::si::dim_speed, vertical_kind> {};
|
||||||
|
|
||||||
// https://en.wikipedia.org/wiki/Flight_planning#Units_of_measurement
|
// https://en.wikipedia.org/wiki/Flight_planning#Units_of_measurement
|
||||||
// length
|
// length
|
||||||
@@ -88,7 +89,7 @@ using altitude = units::quantity_point_kind<vertical_point_kind, units::isq::si:
|
|||||||
|
|
||||||
// time
|
// time
|
||||||
using duration = units::isq::si::time<units::isq::si::second>;
|
using duration = units::isq::si::time<units::isq::si::second>;
|
||||||
using timestamp = units::quantity_point<units::isq::si::dim_time, units::isq::si::second>;
|
using timestamp = units::quantity_point<units::clock_origin<std::chrono::system_clock>, units::isq::si::second>;
|
||||||
|
|
||||||
// speed
|
// speed
|
||||||
using velocity = units::quantity_kind<velocity_kind, units::isq::si::kilometre_per_hour>;
|
using velocity = units::quantity_kind<velocity_kind, units::isq::si::kilometre_per_hour>;
|
||||||
|
@@ -20,10 +20,6 @@
|
|||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
|
|
||||||
#define UNITS_ALIASES
|
|
||||||
#define UNITS_LITERALS
|
|
||||||
#define UNITS_REFERENCES
|
|
||||||
|
|
||||||
#include <units/format.h>
|
#include <units/format.h>
|
||||||
#include <units/isq/si/international/length.h>
|
#include <units/isq/si/international/length.h>
|
||||||
#include <units/isq/si/international/speed.h> // IWYU pragma: keep
|
#include <units/isq/si/international/speed.h> // IWYU pragma: keep
|
||||||
|
@@ -28,7 +28,10 @@ cmake_minimum_required(VERSION 3.2)
|
|||||||
function(add_example target)
|
function(add_example target)
|
||||||
add_executable(${target} ${target}.cpp)
|
add_executable(${target} ${target}.cpp)
|
||||||
target_link_libraries(${target} PRIVATE ${ARGN})
|
target_link_libraries(${target} PRIVATE ${ARGN})
|
||||||
target_compile_definitions(${target} PRIVATE UNITS_REFERENCES)
|
target_compile_definitions(${target} PRIVATE
|
||||||
|
UNITS_NO_LITERALS
|
||||||
|
UNITS_NO_ALIASES
|
||||||
|
)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
add_example(kalman_filter-example_1 mp-units::core-fmt mp-units::si)
|
add_example(kalman_filter-example_1 mp-units::core-fmt mp-units::si)
|
||||||
|
@@ -28,7 +28,10 @@ cmake_minimum_required(VERSION 3.2)
|
|||||||
function(add_example target)
|
function(add_example target)
|
||||||
add_executable(${target}-literals ${target}.cpp)
|
add_executable(${target}-literals ${target}.cpp)
|
||||||
target_link_libraries(${target}-literals PRIVATE ${ARGN})
|
target_link_libraries(${target}-literals PRIVATE ${ARGN})
|
||||||
target_compile_definitions(${target}-literals PRIVATE UNITS_LITERALS)
|
target_compile_definitions(${target}-literals PRIVATE
|
||||||
|
UNITS_NO_REFERENCES
|
||||||
|
UNITS_NO_ALIASES
|
||||||
|
)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international)
|
add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international)
|
||||||
@@ -42,7 +45,10 @@ add_example(unknown_dimension mp-units::core-io mp-units::si)
|
|||||||
|
|
||||||
if(NOT UNITS_LIBCXX)
|
if(NOT UNITS_LIBCXX)
|
||||||
add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer)
|
add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer)
|
||||||
target_compile_definitions(glide_computer_example-literals PRIVATE UNITS_LITERALS)
|
target_compile_definitions(glide_computer_example-literals PRIVATE
|
||||||
|
UNITS_NO_REFERENCES
|
||||||
|
UNITS_NO_ALIASES
|
||||||
|
)
|
||||||
|
|
||||||
find_package(linear_algebra CONFIG REQUIRED)
|
find_package(linear_algebra CONFIG REQUIRED)
|
||||||
add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si)
|
add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si)
|
||||||
|
@@ -28,7 +28,10 @@ cmake_minimum_required(VERSION 3.2)
|
|||||||
function(add_example target)
|
function(add_example target)
|
||||||
add_executable(${target}-references ${target}.cpp)
|
add_executable(${target}-references ${target}.cpp)
|
||||||
target_link_libraries(${target}-references PRIVATE ${ARGN})
|
target_link_libraries(${target}-references PRIVATE ${ARGN})
|
||||||
target_compile_definitions(${target}-references PRIVATE UNITS_REFERENCES)
|
target_compile_definitions(${target}-references PRIVATE
|
||||||
|
UNITS_NO_LITERALS
|
||||||
|
UNITS_NO_ALIASES
|
||||||
|
)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international)
|
add_example(avg_speed mp-units::core-io mp-units::si mp-units::si-cgs mp-units::si-international)
|
||||||
@@ -42,7 +45,10 @@ add_example(unknown_dimension mp-units::core-io mp-units::si)
|
|||||||
|
|
||||||
if(NOT UNITS_LIBCXX)
|
if(NOT UNITS_LIBCXX)
|
||||||
add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer)
|
add_example(glide_computer_example mp-units::core-fmt mp-units::si-international glide_computer)
|
||||||
target_compile_definitions(glide_computer_example-references PRIVATE UNITS_REFERENCES)
|
target_compile_definitions(glide_computer_example-references PRIVATE
|
||||||
|
UNITS_NO_LITERALS
|
||||||
|
UNITS_NO_ALIASES
|
||||||
|
)
|
||||||
|
|
||||||
find_package(linear_algebra CONFIG REQUIRED)
|
find_package(linear_algebra CONFIG REQUIRED)
|
||||||
add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si)
|
add_example(linear_algebra mp-units::core-fmt mp-units::core-io mp-units::si)
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
cmake_minimum_required(VERSION 3.15)
|
cmake_minimum_required(VERSION 3.15)
|
||||||
project(mp-units
|
project(mp-units
|
||||||
VERSION 0.7.0
|
VERSION 0.8.0
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -205,6 +205,52 @@ concept UnitOf =
|
|||||||
Dimension<D> &&
|
Dimension<D> &&
|
||||||
std::same_as<typename U::reference, typename dimension_unit<D>::reference>;
|
std::same_as<typename U::reference, typename dimension_unit<D>::reference>;
|
||||||
|
|
||||||
|
// PointOrigin
|
||||||
|
|
||||||
|
template<Dimension D>
|
||||||
|
struct point_origin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A concept matching a point origin
|
||||||
|
*
|
||||||
|
* Satisfied by types derived from an specialization of @c point_origin.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
concept PointOrigin = is_derived_from_specialization_of<T, point_origin> &&
|
||||||
|
requires {
|
||||||
|
typename T::dimension;
|
||||||
|
requires Dimension<typename T::dimension>;
|
||||||
|
typename T::point_origin;
|
||||||
|
requires std::same_as<typename T::point_origin, point_origin<typename T::dimension>>;
|
||||||
|
requires !std::same_as<T, point_origin<typename T::dimension>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
// RebindablePointOriginFor
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename O, typename D>
|
||||||
|
struct rebind_point_origin_dimension_impl {
|
||||||
|
using type = typename O::template rebind<D>;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<PointOrigin O, Dimension D>
|
||||||
|
using rebind_point_origin_dimension = typename conditional<is_same_v<typename O::dimension, D>, std::type_identity<O>,
|
||||||
|
detail::rebind_point_origin_dimension_impl<O, D>>::type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A concept predicating the possibility of changing an origin's dimension
|
||||||
|
*
|
||||||
|
* Satisfied by point origins whose dimension can be made to be `D`.
|
||||||
|
*/
|
||||||
|
template<typename T, typename D>
|
||||||
|
concept RebindablePointOriginFor =
|
||||||
|
requires { typename rebind_point_origin_dimension<T, D>; } &&
|
||||||
|
PointOrigin<rebind_point_origin_dimension<T, D>> &&
|
||||||
|
std::same_as<D, typename rebind_point_origin_dimension<T, D>::dimension>;
|
||||||
|
|
||||||
// Kind
|
// Kind
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
@@ -216,7 +262,7 @@ struct _kind_base;
|
|||||||
template<typename T, template<typename...> typename Base>
|
template<typename T, template<typename...> typename Base>
|
||||||
concept kind_impl_ =
|
concept kind_impl_ =
|
||||||
is_derived_from_specialization_of<T, Base> &&
|
is_derived_from_specialization_of<T, Base> &&
|
||||||
requires(T* t) {
|
requires {
|
||||||
typename T::base_kind;
|
typename T::base_kind;
|
||||||
typename T::dimension;
|
typename T::dimension;
|
||||||
requires Dimension<typename T::dimension>;
|
requires Dimension<typename T::dimension>;
|
||||||
@@ -236,7 +282,7 @@ concept Kind =
|
|||||||
// PointKind
|
// PointKind
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<Kind>
|
template<Kind, PointOrigin>
|
||||||
struct _point_kind_base;
|
struct _point_kind_base;
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
@@ -247,7 +293,12 @@ struct _point_kind_base;
|
|||||||
* Satisfied by all point kind types derived from an specialization of @c point_kind.
|
* Satisfied by all point kind types derived from an specialization of @c point_kind.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept PointKind = kind_impl_<T, detail::_point_kind_base>;
|
concept PointKind =
|
||||||
|
kind_impl_<T, detail::_point_kind_base> &&
|
||||||
|
requires { typename T::origin; } &&
|
||||||
|
PointOrigin<typename T::origin> &&
|
||||||
|
std::same_as<typename T::dimension, typename T::base_kind::dimension> &&
|
||||||
|
std::same_as<typename T::dimension, typename T::origin::dimension>;
|
||||||
|
|
||||||
// Reference
|
// Reference
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
@@ -31,7 +31,7 @@ namespace units {
|
|||||||
template<Dimension D, UnitOf<D> U, Representation Rep>
|
template<Dimension D, UnitOf<D> U, Representation Rep>
|
||||||
class quantity;
|
class quantity;
|
||||||
|
|
||||||
template<Dimension D, UnitOf<D> U, Representation Rep>
|
template<PointOrigin O, UnitOf<typename O::dimension> U, Representation Rep>
|
||||||
class quantity_point;
|
class quantity_point;
|
||||||
|
|
||||||
template<Kind K, UnitOf<typename K::dimension> U, Representation Rep>
|
template<Kind K, UnitOf<typename K::dimension> U, Representation Rep>
|
||||||
@@ -99,7 +99,8 @@ template<units::QuantityPoint QP1, units::QuantityPointEquivalentTo<QP1> QP2>
|
|||||||
requires requires { typename common_type_t<typename QP1::rep, typename QP2::rep>; }
|
requires requires { typename common_type_t<typename QP1::rep, typename QP2::rep>; }
|
||||||
struct common_type<QP1, QP2> {
|
struct common_type<QP1, QP2> {
|
||||||
using type = units::quantity_point<
|
using type = units::quantity_point<
|
||||||
typename common_type_t<typename QP1::quantity_type, typename QP2::quantity_type>::dimension,
|
units::rebind_point_origin_dimension<typename QP1::origin,
|
||||||
|
typename common_type_t<typename QP1::quantity_type, typename QP2::quantity_type>::dimension>,
|
||||||
typename common_type_t<typename QP1::quantity_type, typename QP2::quantity_type>::unit,
|
typename common_type_t<typename QP1::quantity_type, typename QP2::quantity_type>::unit,
|
||||||
typename common_type_t<typename QP1::quantity_type, typename QP2::quantity_type>::rep>;
|
typename common_type_t<typename QP1::quantity_type, typename QP2::quantity_type>::rep>;
|
||||||
};
|
};
|
||||||
|
@@ -80,16 +80,16 @@ template<typename... Es>
|
|||||||
inline constexpr int negative_exp_count = ((Es::num < 0 ? 1 : 0) + ... + 0);
|
inline constexpr int negative_exp_count = ((Es::num < 0 ? 1 : 0) + ... + 0);
|
||||||
|
|
||||||
template<typename... Us, typename... Es, std::size_t... Idxs>
|
template<typename... Us, typename... Es, std::size_t... Idxs>
|
||||||
constexpr auto deduced_symbol_text(exponent_list<Es...>, std::index_sequence<Idxs...>)
|
constexpr auto derived_symbol_text(exponent_list<Es...>, std::index_sequence<Idxs...>)
|
||||||
{
|
{
|
||||||
constexpr auto neg_exp = negative_exp_count<Es...>;
|
constexpr auto neg_exp = negative_exp_count<Es...>;
|
||||||
return (exp_text<Es, Us::symbol, neg_exp, Idxs>() + ...);
|
return (exp_text<Es, Us::symbol, neg_exp, Idxs>() + ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<DerivedDimension Dim, Unit... Us>
|
template<DerivedDimension Dim, Unit... Us>
|
||||||
constexpr auto deduced_symbol_text()
|
constexpr auto derived_symbol_text()
|
||||||
{
|
{
|
||||||
return deduced_symbol_text<Us...>(typename Dim::recipe(), std::index_sequence_for<Us...>());
|
return derived_symbol_text<Us...>(typename Dim::recipe(), std::index_sequence_for<Us...>());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace units::detail
|
} // namespace units::detail
|
@@ -33,7 +33,7 @@ inline constexpr bool same_scaled_units = false;
|
|||||||
template<typename... Es, Unit... Us>
|
template<typename... Es, Unit... Us>
|
||||||
inline constexpr bool same_scaled_units<exponent_list<Es...>, Us...> = (UnitOf<Us, typename Es::dimension> && ...);
|
inline constexpr bool same_scaled_units<exponent_list<Es...>, Us...> = (UnitOf<Us, typename Es::dimension> && ...);
|
||||||
|
|
||||||
// deduced_unit
|
// derived_unit
|
||||||
|
|
||||||
template<Exponent E>
|
template<Exponent E>
|
||||||
constexpr ratio inverse_if_negative(const ratio& r)
|
constexpr ratio inverse_if_negative(const ratio& r)
|
||||||
@@ -51,6 +51,6 @@ constexpr ratio derived_ratio(exponent_list<Es...>)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<DerivedDimension D, Unit... Us>
|
template<DerivedDimension D, Unit... Us>
|
||||||
using deduced_unit = scaled_unit<derived_ratio<Us...>(typename D::recipe()), typename D::coherent_unit::reference>;
|
using derived_unit = scaled_unit<derived_ratio<Us...>(typename D::recipe()), typename D::coherent_unit::reference>;
|
||||||
|
|
||||||
} // namespace units::detail
|
} // namespace units::detail
|
@@ -81,29 +81,51 @@ template<Unit U1, Dimension D1, Unit U2, Dimension D2>
|
|||||||
struct equivalent_unit : std::disjunction<equivalent_impl<U1, U2>,
|
struct equivalent_unit : std::disjunction<equivalent_impl<U1, U2>,
|
||||||
std::bool_constant<U1::ratio / dimension_unit<D1>::ratio == U2::ratio / dimension_unit<D2>::ratio>> {};
|
std::bool_constant<U1::ratio / dimension_unit<D1>::ratio == U2::ratio / dimension_unit<D2>::ratio>> {};
|
||||||
|
|
||||||
|
// point origins
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
concept EquivalentPointOrigins =
|
||||||
|
RebindablePointOriginFor<T, typename U::dimension> && RebindablePointOriginFor<U, typename T::dimension> &&
|
||||||
|
std::same_as<T, rebind_point_origin_dimension<U, typename T::dimension>> &&
|
||||||
|
std::same_as<U, rebind_point_origin_dimension<T, typename U::dimension>>;
|
||||||
|
|
||||||
|
template<PointOrigin T, PointOrigin U>
|
||||||
|
struct equivalent_impl<T, U> : std::bool_constant<
|
||||||
|
EquivalentPointOrigins<T, U> && equivalent_impl<typename T::dimension, typename U::dimension>::value> {};
|
||||||
|
|
||||||
|
|
||||||
// (point) kinds
|
// (point) kinds
|
||||||
|
|
||||||
template<typename T, typename U>
|
template<Kind T, Kind U>
|
||||||
requires (Kind<T> && Kind<U>) || (PointKind<T> && PointKind<U>)
|
|
||||||
struct equivalent_impl<T, U> :
|
struct equivalent_impl<T, U> :
|
||||||
std::conjunction<std::is_same<typename T::base_kind, typename U::base_kind>,
|
std::conjunction<std::is_same<typename T::base_kind, typename U::base_kind>,
|
||||||
equivalent_impl<typename T::dimension, typename U::dimension>> {};
|
equivalent_impl<typename T::dimension, typename U::dimension>> {};
|
||||||
|
|
||||||
|
template<PointKind T, PointKind U>
|
||||||
|
struct equivalent_impl<T, U> :
|
||||||
|
std::conjunction<equivalent_impl<typename T::base_kind, typename U::base_kind>,
|
||||||
|
equivalent_impl<typename T::origin, typename U::origin>> {};
|
||||||
|
|
||||||
|
|
||||||
// quantities, quantity points, quantity (point) kinds
|
// quantities, quantity points, quantity (point) kinds
|
||||||
|
|
||||||
template<typename Q1, typename Q2>
|
template<Quantity Q1, Quantity Q2>
|
||||||
requires (Quantity<Q1> && Quantity<Q2>) || (QuantityPoint<Q1> && QuantityPoint<Q2>)
|
|
||||||
struct equivalent_impl<Q1, Q2> : std::conjunction<equivalent_impl<typename Q1::dimension, typename Q2::dimension>,
|
struct equivalent_impl<Q1, Q2> : std::conjunction<equivalent_impl<typename Q1::dimension, typename Q2::dimension>,
|
||||||
equivalent_unit<typename Q1::unit, typename Q1::dimension,
|
equivalent_unit<typename Q1::unit, typename Q1::dimension,
|
||||||
typename Q2::unit, typename Q2::dimension>> {};
|
typename Q2::unit, typename Q2::dimension>> {};
|
||||||
|
|
||||||
template<typename QK1, typename QK2>
|
template<QuantityPoint QP1, QuantityPoint QP2>
|
||||||
requires (QuantityKind<QK1> && QuantityKind<QK2>) || (QuantityPointKind<QK1> && QuantityPointKind<QK2>)
|
struct equivalent_impl<QP1, QP2> : std::conjunction<equivalent_impl<typename QP1::quantity_type, typename QP2::quantity_type>,
|
||||||
|
equivalent_impl<typename QP1::origin, typename QP2::origin>> {};
|
||||||
|
|
||||||
|
template<QuantityKind QK1, QuantityKind QK2>
|
||||||
struct equivalent_impl<QK1, QK2> : std::conjunction<equivalent_impl<typename QK1::kind_type, typename QK2::kind_type>,
|
struct equivalent_impl<QK1, QK2> : std::conjunction<equivalent_impl<typename QK1::kind_type, typename QK2::kind_type>,
|
||||||
equivalent_impl<typename QK1::quantity_type, typename QK2::quantity_type>> {};
|
equivalent_impl<typename QK1::quantity_type, typename QK2::quantity_type>> {};
|
||||||
|
|
||||||
|
template<QuantityPointKind QPK1, QuantityPointKind QPK2>
|
||||||
|
struct equivalent_impl<QPK1, QPK2> : std::conjunction<equivalent_impl<typename QPK1::quantity_kind_type, typename QPK2::quantity_kind_type>,
|
||||||
|
equivalent_impl<typename QPK1::origin, typename QPK2::origin>> {};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
|
@@ -85,21 +85,20 @@ template<typename Q1, typename Q2>
|
|||||||
concept QuantityEquivalentTo = Quantity<Q1> && QuantityOf<Q2, typename Q1::dimension>;
|
concept QuantityEquivalentTo = Quantity<Q1> && QuantityOf<Q2, typename Q1::dimension>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A concept matching all quantity points with provided dimension
|
* @brief A concept matching all quantity points of the provided origin
|
||||||
*
|
*
|
||||||
* Satisfied by all quantity points with a dimension being the instantiation derived from
|
* Satisfied by all quantity points with an origin equivalent to the provided one.
|
||||||
* the provided dimension type.
|
|
||||||
*/
|
*/
|
||||||
template<typename QP, typename Dim>
|
template<typename QP, typename Orig>
|
||||||
concept QuantityPointOf = QuantityPoint<QP> && Dimension<Dim> && equivalent<typename QP::dimension, Dim>;
|
concept QuantityPointOf = QuantityPoint<QP> && PointOrigin<Orig> && equivalent<typename QP::origin, Orig>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A concept matching two equivalent quantity points
|
* @brief A concept matching two equivalent quantity points
|
||||||
*
|
*
|
||||||
* Satisfied by quantity points having equivalent dimensions.
|
* Satisfied by quantity points having equivalent origins.
|
||||||
*/
|
*/
|
||||||
template<typename QP1, typename QP2>
|
template<typename QP1, typename QP2>
|
||||||
concept QuantityPointEquivalentTo = QuantityPoint<QP1> && QuantityPointOf<QP2, typename QP1::dimension>;
|
concept QuantityPointEquivalentTo = QuantityPoint<QP1> && QuantityPointOf<QP2, typename QP1::origin>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A concept matching only quantity kinds of a specific kind.
|
* @brief A concept matching only quantity kinds of a specific kind.
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/bits/deduced_symbol_text.h>
|
#include <units/bits/derived_symbol_text.h>
|
||||||
#include <units/bits/external/text_tools.h>
|
#include <units/bits/external/text_tools.h>
|
||||||
#include <units/prefix.h>
|
#include <units/prefix.h>
|
||||||
#include <units/derived_dimension.h>
|
#include <units/derived_dimension.h>
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
#include <units/customization_points.h>
|
#include <units/customization_points.h>
|
||||||
// IWYU pragma: begin_exports
|
// IWYU pragma: begin_exports
|
||||||
#include <units/isq/si/time.h>
|
#include <units/isq/si/time.h>
|
||||||
|
#include <units/point_origin.h>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
// IWYU pragma: end_exports
|
// IWYU pragma: end_exports
|
||||||
|
|
||||||
@@ -38,10 +39,13 @@ struct quantity_like_traits<std::chrono::duration<Rep, Period>> {
|
|||||||
[[nodiscard]] static constexpr rep number(const std::chrono::duration<Rep, Period>& q) { return q.count(); }
|
[[nodiscard]] static constexpr rep number(const std::chrono::duration<Rep, Period>& q) { return q.count(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename C>
|
||||||
|
struct clock_origin : point_origin<isq::si::dim_time> { };
|
||||||
|
|
||||||
template<typename C, typename Rep, typename Period>
|
template<typename C, typename Rep, typename Period>
|
||||||
struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::duration<Rep, Period>>> {
|
struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::duration<Rep, Period>>> {
|
||||||
using dimension = isq::si::dim_time;
|
using origin = clock_origin<C>;
|
||||||
using unit = downcast_unit<dimension, ratio(Period::num, Period::den)>;
|
using unit = downcast_unit<typename origin::dimension, ratio(Period::num, Period::den)>;
|
||||||
using rep = Rep;
|
using rep = Rep;
|
||||||
[[nodiscard]] static constexpr auto relative(
|
[[nodiscard]] static constexpr auto relative(
|
||||||
const std::chrono::time_point<C, std::chrono::duration<Rep, Period>>& qp) {
|
const std::chrono::time_point<C, std::chrono::duration<Rep, Period>>& qp) {
|
||||||
@@ -49,4 +53,11 @@ struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::durati
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename C, typename Rep, typename Period>
|
||||||
|
inline constexpr bool is_quantity_point_like<std::chrono::time_point<C, std::chrono::duration<Rep, Period>>> = true;
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units
|
||||||
|
@@ -88,7 +88,7 @@ struct quantity_like_traits;
|
|||||||
/**
|
/**
|
||||||
* @brief Provides support for external quantity point-like types
|
* @brief Provides support for external quantity point-like types
|
||||||
*
|
*
|
||||||
* The type trait should provide the following nested type aliases: @c dimension, @c unit, @c rep,
|
* The type trait should provide the following nested type aliases: @c origin, @c unit, @c rep,
|
||||||
* and a static member function @c relative(T) that will return the quantity-like value of the quantity point.
|
* and a static member function @c relative(T) that will return the quantity-like value of the quantity point.
|
||||||
*
|
*
|
||||||
* Usage example can be found in @c units/chrono.h header file.
|
* Usage example can be found in @c units/chrono.h header file.
|
||||||
|
@@ -43,7 +43,7 @@ concept Angle = QuantityOfT<T, dim_angle>;
|
|||||||
template<UnitOf<dim_angle<>> U, Representation Rep = double>
|
template<UnitOf<dim_angle<>> U, Representation Rep = double>
|
||||||
using angle = quantity<dim_angle<>, U, Rep>;
|
using angle = quantity<dim_angle<>, U, Rep>;
|
||||||
|
|
||||||
#ifdef UNITS_LITERALS
|
#ifndef UNITS_NO_LITERALS
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
@@ -53,9 +53,9 @@ constexpr auto operator"" _q_rad(long double l) { return angle<radian, long doub
|
|||||||
|
|
||||||
} // namespace literals
|
} // namespace literals
|
||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_NO_LITERALS
|
||||||
|
|
||||||
#ifdef UNITS_REFERENCES
|
#ifndef UNITS_NO_REFERENCES
|
||||||
|
|
||||||
namespace angle_references {
|
namespace angle_references {
|
||||||
|
|
||||||
@@ -69,6 +69,6 @@ using namespace angle_references;
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
#endif // UNITS_REFERENCES
|
#endif // UNITS_NO_REFERENCES
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units
|
||||||
|
@@ -27,6 +27,9 @@
|
|||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
|
|
||||||
|
template<Dimension D>
|
||||||
|
struct dynamic_origin;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<typename K, Dimension D>
|
template<typename K, Dimension D>
|
||||||
@@ -35,10 +38,11 @@ struct _kind_base : downcast_base<_kind_base<K, D>> {
|
|||||||
using dimension = D;
|
using dimension = D;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<Kind K>
|
template<Kind K, PointOrigin O>
|
||||||
struct _point_kind_base : downcast_base<_point_kind_base<K>> {
|
struct _point_kind_base : downcast_base<_point_kind_base<K, O>> {
|
||||||
using base_kind = K;
|
using base_kind = K;
|
||||||
using dimension = typename K::dimension;
|
using dimension = typename K::dimension;
|
||||||
|
using origin = O;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
@@ -47,18 +51,18 @@ template<Kind K, Dimension D>
|
|||||||
requires Kind<downcast<detail::_kind_base<typename K::base_kind, D>>>
|
requires Kind<downcast<detail::_kind_base<typename K::base_kind, D>>>
|
||||||
using downcast_kind = downcast<detail::_kind_base<typename K::base_kind, D>>;
|
using downcast_kind = downcast<detail::_kind_base<typename K::base_kind, D>>;
|
||||||
|
|
||||||
template<Kind K>
|
template<Kind K, PointOrigin O = dynamic_origin<typename K::dimension>>
|
||||||
requires PointKind<downcast<detail::_point_kind_base<K>>>
|
requires PointKind<downcast<detail::_point_kind_base<K, O>>>
|
||||||
using downcast_point_kind = downcast<detail::_point_kind_base<K>>;
|
using downcast_point_kind = downcast<detail::_point_kind_base<K, O>>;
|
||||||
|
|
||||||
template<typename K, Dimension D>
|
template<typename K, Dimension D>
|
||||||
struct kind : downcast_dispatch<K, detail::_kind_base<K, D>> {};
|
struct kind : downcast_dispatch<K, detail::_kind_base<K, D>> {};
|
||||||
|
|
||||||
template<typename DK, Kind BK, Dimension D>
|
template<typename DK, Dimension D, Kind BK>
|
||||||
requires std::same_as<BK, typename BK::base_kind>
|
requires std::same_as<BK, typename BK::base_kind>
|
||||||
struct derived_kind : downcast_dispatch<DK, detail::_kind_base<BK, D>> {};
|
struct derived_kind : downcast_dispatch<DK, detail::_kind_base<BK, D>> {};
|
||||||
|
|
||||||
template<typename DPK, Kind BK>
|
template<typename DPK, Kind BK, PointOrigin O = dynamic_origin<typename BK::dimension>>
|
||||||
struct point_kind : downcast_dispatch<DPK, detail::_point_kind_base<BK>> {};
|
struct point_kind : downcast_dispatch<DPK, detail::_point_kind_base<BK, O>> {};
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units
|
||||||
|
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(const quantity&) = default;
|
||||||
quantity(quantity&&) = default;
|
quantity(quantity&&) = default;
|
||||||
|
|
||||||
template<safe_convertible_to_<rep> Value>
|
template<typename Value>
|
||||||
constexpr explicit(!(is_same_v<dimension, dim_one> && is_same_v<unit, ::units::one>))
|
requires safe_convertible_to_<std::remove_cvref_t<Value>, rep>
|
||||||
quantity(const Value& v) : number_(v) {}
|
constexpr explicit(!(std::same_as<dimension, dim_one> && std::same_as<unit, ::units::one>))
|
||||||
|
quantity(Value&& v) : number_(std::forward<Value>(v)) {}
|
||||||
|
|
||||||
template<safe_castable_to_<quantity> Q>
|
template<safe_castable_to_<quantity> Q>
|
||||||
constexpr explicit(false) quantity(const Q& q) : number_(quantity_cast<quantity>(q).number()) {}
|
constexpr explicit(false) quantity(const Q& q) : number_(quantity_cast<quantity>(q).number()) {}
|
||||||
@@ -162,7 +163,10 @@ public:
|
|||||||
quantity& operator=(quantity&&) = default;
|
quantity& operator=(quantity&&) = default;
|
||||||
|
|
||||||
// data access
|
// data access
|
||||||
[[nodiscard]] constexpr rep number() const noexcept { return number_; }
|
[[nodiscard]] constexpr rep& number() & noexcept { return number_; }
|
||||||
|
[[nodiscard]] constexpr const rep& number() const & noexcept { return number_; }
|
||||||
|
[[nodiscard]] constexpr rep&& number() && noexcept { return std::move(number_); }
|
||||||
|
[[nodiscard]] constexpr const rep&& number() const && noexcept { return std::move(number_); }
|
||||||
|
|
||||||
// member unary operators
|
// member unary operators
|
||||||
[[nodiscard]] constexpr Quantity auto operator+() const
|
[[nodiscard]] constexpr Quantity auto operator+() const
|
||||||
@@ -363,11 +367,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr Quantity auto operator%(const quantity& lhs, const quantity& rhs)
|
[[nodiscard]] friend constexpr Quantity auto operator%(const quantity& lhs, const quantity& rhs)
|
||||||
requires (!floating_point_<rep>) && is_same_v<unit, units::one> &&
|
requires (!floating_point_<rep>) &&
|
||||||
invoke_result_convertible_to_<rep, std::modulus<>, rep, rep>
|
invoke_result_convertible_to_<rep, std::modulus<>, rep, rep>
|
||||||
{
|
{
|
||||||
gsl_ExpectsAudit(rhs.number() != quantity_values<rep>::zero());
|
gsl_ExpectsAudit(rhs.number() != quantity_values<rep>::zero());
|
||||||
return units::quantity(lhs.number() % rhs.number());
|
using ret = quantity<D, U, std::invoke_result_t<std::modulus<>, rep, rep>>;
|
||||||
|
return ret(lhs.number() % rhs.number());
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr auto operator<=>(const quantity& lhs, const quantity& rhs)
|
[[nodiscard]] friend constexpr auto operator<=>(const quantity& lhs, const quantity& rhs)
|
||||||
@@ -422,25 +427,15 @@ template<Quantity Q1, Quantity Q2>
|
|||||||
return detail::make_quantity<Q1::reference / Q2::reference>(lhs.number() / rhs.number());
|
return detail::make_quantity<Q1::reference / Q2::reference>(lhs.number() / rhs.number());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename D1, typename U1, typename Rep1, typename U2, typename Rep2>
|
template<Quantity Q1, Quantity Q2>
|
||||||
requires (!floating_point_<Rep1>) && (!floating_point_<Rep2>) &&
|
|
||||||
quantity_value_for_<std::modulus<>, Rep1, Rep2>
|
|
||||||
[[nodiscard]] constexpr Quantity auto operator%(const quantity<D1, U1, Rep1>& lhs, const quantity<dim_one, U2, Rep2>& rhs)
|
|
||||||
{
|
|
||||||
gsl_ExpectsAudit(rhs.number() != quantity_values<Rep2>::zero());
|
|
||||||
using unit = downcast_unit<D1, U1::ratio * U2::ratio>;
|
|
||||||
using ret = quantity<D1, unit, std::invoke_result_t<std::modulus<>, Rep1, Rep2>>;
|
|
||||||
return ret(lhs.number() % rhs.number());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Quantity Q1, QuantityEquivalentTo<Q1> Q2>
|
|
||||||
requires (!floating_point_<typename Q1::rep>) && (!floating_point_<typename Q2::rep>) &&
|
requires (!floating_point_<typename Q1::rep>) && (!floating_point_<typename Q2::rep>) &&
|
||||||
|
(QuantityEquivalentTo<Q2, Q1> || Dimensionless<Q2>) &&
|
||||||
quantity_value_for_<std::modulus<>, typename Q1::rep, typename Q2::rep>
|
quantity_value_for_<std::modulus<>, typename Q1::rep, typename Q2::rep>
|
||||||
[[nodiscard]] constexpr Quantity auto operator%(const Q1& lhs, const Q2& rhs)
|
[[nodiscard]] constexpr Quantity auto operator%(const Q1& lhs, const Q2& rhs)
|
||||||
{
|
{
|
||||||
gsl_ExpectsAudit(rhs.number() != quantity_values<typename Q2::rep>::zero());
|
gsl_ExpectsAudit(rhs.number() != quantity_values<typename Q2::rep>::zero());
|
||||||
using ret = common_quantity_for<std::modulus<>, Q1, Q2>;
|
using ret = quantity<typename Q1::dimension, typename Q1::unit, std::invoke_result_t<std::modulus<>, typename Q1::rep, typename Q2::rep>>;
|
||||||
return ret(ret(lhs).number() % ret(rhs).number());
|
return ret(lhs.number() % rhs.number());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Quantity Q1, QuantityEquivalentTo<Q1> Q2>
|
template<Quantity Q1, QuantityEquivalentTo<Q1> Q2>
|
||||||
|
@@ -39,7 +39,7 @@ namespace units {
|
|||||||
template<Dimension D, UnitOf<D> U, Representation Rep>
|
template<Dimension D, UnitOf<D> U, Representation Rep>
|
||||||
class quantity;
|
class quantity;
|
||||||
|
|
||||||
template<Dimension D, UnitOf<D> U, Representation Rep>
|
template<PointOrigin O, UnitOf<typename O::dimension> U, Representation Rep>
|
||||||
class quantity_point;
|
class quantity_point;
|
||||||
|
|
||||||
template<Kind K, UnitOf<typename K::dimension> U, Representation Rep>
|
template<Kind K, UnitOf<typename K::dimension> U, Representation Rep>
|
||||||
@@ -234,10 +234,12 @@ template<Representation ToRep, typename D, typename U, scalable_with_<ToRep> Rep
|
|||||||
*
|
*
|
||||||
* @tparam CastSpec a target quantity point type to cast to or anything that works for quantity_cast
|
* @tparam CastSpec a target quantity point type to cast to or anything that works for quantity_cast
|
||||||
*/
|
*/
|
||||||
template<typename CastSpec, typename D, typename U, typename Rep>
|
template<typename CastSpec, typename O, typename U, typename Rep>
|
||||||
requires is_specialization_of<CastSpec, quantity_point> ||
|
[[nodiscard]] constexpr auto quantity_point_cast(const quantity_point<O, U, Rep>& qp)
|
||||||
requires(quantity<D, U, Rep> q) { quantity_cast<CastSpec>(q); }
|
requires requires { requires is_specialization_of<CastSpec, quantity_point>;
|
||||||
[[nodiscard]] constexpr auto quantity_point_cast(const quantity_point<D, U, Rep>& qp)
|
requires requires { quantity_cast<typename CastSpec::quantity_type>(qp.relative()); };
|
||||||
|
requires equivalent<O, typename CastSpec::origin>; } || // TODO: Simplify when Clang catches up.
|
||||||
|
requires { quantity_cast<CastSpec>(qp.relative()); }
|
||||||
{
|
{
|
||||||
if constexpr (is_specialization_of<CastSpec, quantity_point>)
|
if constexpr (is_specialization_of<CastSpec, quantity_point>)
|
||||||
return quantity_point(quantity_cast<typename CastSpec::quantity_type>(qp.relative()));
|
return quantity_point(quantity_cast<typename CastSpec::quantity_type>(qp.relative()));
|
||||||
@@ -261,11 +263,11 @@ template<typename CastSpec, typename D, typename U, typename Rep>
|
|||||||
* @tparam ToD a dimension type to use for a target quantity
|
* @tparam ToD a dimension type to use for a target quantity
|
||||||
* @tparam ToU a unit type to use for a target quantity
|
* @tparam ToU a unit type to use for a target quantity
|
||||||
*/
|
*/
|
||||||
template<Dimension ToD, Unit ToU, typename D, typename U, typename Rep>
|
template<Dimension ToD, Unit ToU, typename O, typename U, typename Rep>
|
||||||
requires equivalent<ToD, D> && UnitOf<ToU, ToD>
|
requires equivalent<ToD, typename O::dimension> && UnitOf<ToU, ToD> && RebindablePointOriginFor<O, ToD>
|
||||||
[[nodiscard]] constexpr auto quantity_point_cast(const quantity_point<D, U, Rep>& q)
|
[[nodiscard]] constexpr auto quantity_point_cast(const quantity_point<O, U, Rep>& q)
|
||||||
{
|
{
|
||||||
return quantity_point_cast<quantity_point<ToD, ToU, Rep>>(q);
|
return quantity_point_cast<quantity_point<rebind_point_origin_dimension<O, ToD>, ToU, Rep>>(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -347,7 +349,8 @@ template<Kind ToK, Unit ToU, typename K, typename U, typename Rep>
|
|||||||
template<typename CastSpec, typename PK, typename U, typename Rep>
|
template<typename CastSpec, typename PK, typename U, typename Rep>
|
||||||
[[nodiscard]] constexpr QuantityPointKind auto quantity_point_kind_cast(const quantity_point_kind<PK, U, Rep>& qpk)
|
[[nodiscard]] constexpr QuantityPointKind auto quantity_point_kind_cast(const quantity_point_kind<PK, U, Rep>& qpk)
|
||||||
requires requires { requires is_specialization_of<CastSpec, quantity_point_kind>;
|
requires requires { requires is_specialization_of<CastSpec, quantity_point_kind>;
|
||||||
requires requires { quantity_kind_cast<typename CastSpec::quantity_kind_type>(qpk.relative()); }; } ||
|
requires requires { quantity_kind_cast<typename CastSpec::quantity_kind_type>(qpk.relative()); };
|
||||||
|
requires equivalent<typename PK::origin, typename CastSpec::point_kind_type::origin>; } ||
|
||||||
requires { requires PointKind<CastSpec> && UnitOf<U, typename CastSpec::dimension>; } ||
|
requires { requires PointKind<CastSpec> && UnitOf<U, typename CastSpec::dimension>; } ||
|
||||||
requires { quantity_kind_cast<CastSpec>(qpk.relative()); } // TODO: Simplify when Clang catches up.
|
requires { quantity_kind_cast<CastSpec>(qpk.relative()); } // TODO: Simplify when Clang catches up.
|
||||||
{
|
{
|
||||||
|
@@ -93,22 +93,25 @@ public:
|
|||||||
quantity_kind(const quantity_kind&) = default;
|
quantity_kind(const quantity_kind&) = default;
|
||||||
quantity_kind(quantity_kind&&) = default;
|
quantity_kind(quantity_kind&&) = default;
|
||||||
|
|
||||||
template<safe_convertible_to_<rep> Value>
|
template<typename T>
|
||||||
requires is_same_v<dimension, dim_one> && std::is_constructible_v<quantity_type, Value>
|
requires
|
||||||
constexpr explicit quantity_kind(const Value& v) : q_(v) {}
|
(Quantity<std::remove_cvref_t<T>> ||
|
||||||
|
QuantityLike<std::remove_cvref_t<T>> ||
|
||||||
template<typename Q>
|
(Dimensionless<quantity_type> && !Quantity<std::remove_cvref_t<T>>)) &&
|
||||||
requires (Quantity<Q> || QuantityLike<Q>) && std::is_constructible_v<quantity_type, Q>
|
std::constructible_from<quantity_type, T>
|
||||||
constexpr explicit quantity_kind(const Q& q) : q_{q} {}
|
constexpr explicit quantity_kind(T&& t) : q_(std::forward<T>(t)) {}
|
||||||
|
|
||||||
template<QuantityKindEquivalentTo<quantity_kind> QK2>
|
template<QuantityKindEquivalentTo<quantity_kind> QK2>
|
||||||
requires std::is_convertible_v<typename QK2::quantity_type, quantity_type>
|
requires std::convertible_to<typename QK2::quantity_type, quantity_type>
|
||||||
constexpr explicit(false) quantity_kind(const QK2& qk) : q_{qk.common()} {}
|
constexpr explicit(false) quantity_kind(const QK2& qk) : q_(qk.common()) {}
|
||||||
|
|
||||||
quantity_kind& operator=(const quantity_kind&) = default;
|
quantity_kind& operator=(const quantity_kind&) = default;
|
||||||
quantity_kind& operator=(quantity_kind&&) = default;
|
quantity_kind& operator=(quantity_kind&&) = default;
|
||||||
|
|
||||||
[[nodiscard]] constexpr quantity_type common() const noexcept { return q_; }
|
[[nodiscard]] constexpr quantity_type& common() & noexcept { return q_; }
|
||||||
|
[[nodiscard]] constexpr const quantity_type& common() const & noexcept { return q_; }
|
||||||
|
[[nodiscard]] constexpr quantity_type&& common() && noexcept { return std::move(q_); }
|
||||||
|
[[nodiscard]] constexpr const quantity_type&& common() const && noexcept { return std::move(q_); }
|
||||||
|
|
||||||
[[nodiscard]] static constexpr quantity_kind zero() noexcept
|
[[nodiscard]] static constexpr quantity_kind zero() noexcept
|
||||||
requires requires { quantity_type::zero(); }
|
requires requires { quantity_type::zero(); }
|
||||||
@@ -225,19 +228,14 @@ public:
|
|||||||
q_ %= rhs;
|
q_ %= rhs;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template<typename Rep2>
|
|
||||||
constexpr quantity_kind& operator%=(const quantity_kind<downcast_kind<K, dim_one>, units::one, Rep2>& rhs)
|
|
||||||
requires requires(quantity_type q) { q %= rhs.common(); }
|
|
||||||
{
|
|
||||||
q_ %= rhs.common();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr quantity_kind& operator%=(const quantity_kind& qk)
|
template<QuantityKind QK>
|
||||||
requires requires(quantity_type q) { q %= qk.common(); }
|
constexpr quantity_kind& operator%=(const QK& rhs)
|
||||||
|
requires (QuantityKindEquivalentTo<QK, quantity_kind> || std::same_as<typename QK::kind_type, downcast_kind<K, dim_one>>) &&
|
||||||
|
requires(quantity_type q) { q %= rhs.common(); }
|
||||||
{
|
{
|
||||||
gsl_ExpectsAudit(qk.common().number() != quantity_values<rep>::zero());
|
gsl_ExpectsAudit(rhs.common().number() != quantity_values<typename QK::rep>::zero());
|
||||||
q_ %= qk.common();
|
q_ %= rhs.common();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// IWYU pragma: begin_exports
|
// IWYU pragma: begin_exports
|
||||||
|
#include <units/point_origin.h>
|
||||||
#include <units/quantity.h>
|
#include <units/quantity.h>
|
||||||
#include <compare>
|
#include <compare>
|
||||||
// IWYU pragma: end_exports
|
// IWYU pragma: end_exports
|
||||||
@@ -34,18 +35,32 @@
|
|||||||
namespace units {
|
namespace units {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A quantity point
|
* @brief A statically unspecified quantity point origin
|
||||||
*
|
*
|
||||||
* An absolute quantity with respect to zero (which represents some origin).
|
* An origin, unspecified in the type system, from which an absolute quantity is measured from.
|
||||||
*
|
*
|
||||||
* @tparam D a dimension of the quantity point (can be either a BaseDimension or a DerivedDimension)
|
* @tparam D a dimension of the quantity point (can be either a BaseDimension or a DerivedDimension)
|
||||||
|
*/
|
||||||
|
template<Dimension D>
|
||||||
|
struct dynamic_origin : point_origin<D> {
|
||||||
|
template<Dimension D2>
|
||||||
|
using rebind = dynamic_origin<D2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A quantity point
|
||||||
|
*
|
||||||
|
* An absolute quantity measured from an origin.
|
||||||
|
*
|
||||||
|
* @tparam O a type that represents the origin from which the quantity point is measured from
|
||||||
* @tparam U a measurement unit of the quantity point
|
* @tparam U a measurement unit of the quantity point
|
||||||
* @tparam Rep a type to be used to represent values of a quantity point
|
* @tparam Rep a type to be used to represent values of a quantity point
|
||||||
*/
|
*/
|
||||||
template<Dimension D, UnitOf<D> U, Representation Rep = double>
|
template<PointOrigin O, UnitOf<typename O::dimension> U, Representation Rep = double>
|
||||||
class quantity_point {
|
class quantity_point {
|
||||||
public:
|
public:
|
||||||
using quantity_type = quantity<D, U, Rep>;
|
using origin = O;
|
||||||
|
using quantity_type = quantity<typename origin::dimension, U, Rep>;
|
||||||
using dimension = typename quantity_type::dimension;
|
using dimension = typename quantity_type::dimension;
|
||||||
using unit = typename quantity_type::unit;
|
using unit = typename quantity_type::unit;
|
||||||
using rep = typename quantity_type::rep;
|
using rep = typename quantity_type::rep;
|
||||||
@@ -59,29 +74,27 @@ public:
|
|||||||
quantity_point(const quantity_point&) = default;
|
quantity_point(const quantity_point&) = default;
|
||||||
quantity_point(quantity_point&&) = default;
|
quantity_point(quantity_point&&) = default;
|
||||||
|
|
||||||
template<safe_convertible_to_<rep> Value>
|
template<typename T>
|
||||||
requires is_same_v<dimension, dim_one> && std::is_constructible_v<quantity_type, Value>
|
requires std::constructible_from<quantity_type, T>
|
||||||
constexpr explicit quantity_point(const Value& v) : q_(v) {}
|
constexpr explicit quantity_point(T&& t) : q_(std::forward<T>(t)) {}
|
||||||
|
|
||||||
constexpr explicit quantity_point(const quantity_type& q) : q_{q} {}
|
template<QuantityPointOf<origin> QP2>
|
||||||
|
requires std::convertible_to<typename QP2::quantity_type, quantity_type>
|
||||||
template<QuantityLike Q>
|
constexpr explicit(false) quantity_point(const QP2& qp) : q_(qp.relative()) {}
|
||||||
requires std::is_constructible_v<quantity_type, Q>
|
|
||||||
constexpr explicit quantity_point(const Q& q) : q_{q} {}
|
|
||||||
|
|
||||||
template<QuantityPointLike QP>
|
template<QuantityPointLike QP>
|
||||||
constexpr explicit quantity_point(const QP& qp)
|
constexpr explicit quantity_point(const QP& qp)
|
||||||
requires std::is_constructible_v<quantity_type, decltype(quantity_point_like_traits<QP>::relative(qp))>
|
requires std::is_constructible_v<quantity_type, decltype(quantity_point_like_traits<QP>::relative(qp))> &&
|
||||||
: q_{quantity_point_like_traits<QP>::relative(qp)} {}
|
equivalent<origin, typename quantity_point_like_traits<QP>::origin>
|
||||||
|
: q_(quantity_point_like_traits<QP>::relative(qp)) {}
|
||||||
template<QuantityPoint QP2>
|
|
||||||
requires std::is_convertible_v<typename QP2::quantity_type, quantity_type>
|
|
||||||
constexpr explicit(false) quantity_point(const QP2& qp) : q_{qp.relative()} {}
|
|
||||||
|
|
||||||
quantity_point& operator=(const quantity_point&) = default;
|
quantity_point& operator=(const quantity_point&) = default;
|
||||||
quantity_point& operator=(quantity_point&&) = default;
|
quantity_point& operator=(quantity_point&&) = default;
|
||||||
|
|
||||||
[[nodiscard]] constexpr quantity_type relative() const noexcept { return q_; }
|
[[nodiscard]] constexpr quantity_type& relative() & noexcept { return q_; }
|
||||||
|
[[nodiscard]] constexpr const quantity_type& relative() const & noexcept { return q_; }
|
||||||
|
[[nodiscard]] constexpr quantity_type&& relative() && noexcept { return std::move(q_); }
|
||||||
|
[[nodiscard]] constexpr const quantity_type&& relative() const && noexcept { return std::move(q_); }
|
||||||
|
|
||||||
[[nodiscard]] static constexpr quantity_point min() noexcept
|
[[nodiscard]] static constexpr quantity_point min() noexcept
|
||||||
requires requires { quantity_type::min(); }
|
requires requires { quantity_type::min(); }
|
||||||
@@ -144,7 +157,8 @@ public:
|
|||||||
{
|
{
|
||||||
const auto q = lhs.relative() + rhs;
|
const auto q = lhs.relative() + rhs;
|
||||||
using q_type = decltype(q);
|
using q_type = decltype(q);
|
||||||
return quantity_point<typename q_type::dimension, typename q_type::unit, typename q_type::rep>(q);
|
return quantity_point<rebind_point_origin_dimension<origin, typename q_type::dimension>, typename q_type::unit,
|
||||||
|
typename q_type::rep>(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
@@ -160,48 +174,51 @@ public:
|
|||||||
{
|
{
|
||||||
const auto q = lhs.relative() - rhs;
|
const auto q = lhs.relative() - rhs;
|
||||||
using q_type = decltype(q);
|
using q_type = decltype(q);
|
||||||
return quantity_point<typename q_type::dimension, typename q_type::unit, typename q_type::rep>(q);
|
return quantity_point<rebind_point_origin_dimension<origin, typename q_type::dimension>, typename q_type::unit,
|
||||||
|
typename q_type::rep>(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantityPoint QP>
|
template<QuantityPointOf<origin> QP>
|
||||||
[[nodiscard]] friend constexpr Quantity auto operator-(const quantity_point& lhs, const QP& rhs)
|
[[nodiscard]] friend constexpr Quantity auto operator-(const quantity_point& lhs, const QP& rhs)
|
||||||
requires requires(quantity_type q) { q - rhs.relative(); }
|
requires requires(quantity_type q) { q - rhs.relative(); }
|
||||||
{
|
{
|
||||||
return lhs.relative() - rhs.relative();
|
return lhs.relative() - rhs.relative();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantityPoint QP>
|
template<QuantityPointOf<origin> QP>
|
||||||
requires std::three_way_comparable_with<quantity_type, typename QP::quantity_type>
|
requires std::three_way_comparable_with<quantity_type, typename QP::quantity_type>
|
||||||
[[nodiscard]] friend constexpr auto operator<=>(const quantity_point& lhs, const QP& rhs)
|
[[nodiscard]] friend constexpr auto operator<=>(const quantity_point& lhs, const QP& rhs)
|
||||||
{
|
{
|
||||||
return lhs.relative() <=> rhs.relative();
|
return lhs.relative() <=> rhs.relative();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantityPoint QP>
|
template<QuantityPointOf<origin> QP>
|
||||||
requires std::equality_comparable_with<quantity_type, typename QP::quantity_type>
|
requires std::equality_comparable_with<quantity_type, typename QP::quantity_type>
|
||||||
[[nodiscard]] friend constexpr bool operator==(const quantity_point& lhs, const QP& rhs)
|
[[nodiscard]] friend constexpr bool operator==(const quantity_point& lhs, const QP& rhs)
|
||||||
{
|
{
|
||||||
return lhs.relative() == rhs.relative();
|
return lhs.relative() == rhs.relative();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<Representation Rep>
|
template<Representation Rep>
|
||||||
explicit(false) quantity_point(Rep) -> quantity_point<dim_one, one, Rep>;
|
explicit quantity_point(Rep) -> quantity_point<dynamic_origin<dim_one>, one, Rep>;
|
||||||
|
|
||||||
|
template<Quantity Q>
|
||||||
|
explicit quantity_point(Q) -> quantity_point<dynamic_origin<typename Q::dimension>, typename Q::unit, typename Q::rep>;
|
||||||
|
|
||||||
template<QuantityLike Q>
|
template<QuantityLike Q>
|
||||||
quantity_point(Q) -> quantity_point<typename quantity_like_traits<Q>::dimension,
|
explicit quantity_point(Q) -> quantity_point<dynamic_origin<typename quantity_like_traits<Q>::dimension>,
|
||||||
typename quantity_like_traits<Q>::unit, typename quantity_like_traits<Q>::rep>;
|
typename quantity_like_traits<Q>::unit, typename quantity_like_traits<Q>::rep>;
|
||||||
|
|
||||||
template<QuantityPointLike QP>
|
template<QuantityPointLike QP>
|
||||||
explicit quantity_point(QP) -> quantity_point<typename quantity_point_like_traits<QP>::dimension,
|
explicit quantity_point(QP) -> quantity_point<typename quantity_point_like_traits<QP>::origin,
|
||||||
typename quantity_point_like_traits<QP>::unit,
|
typename quantity_point_like_traits<QP>::unit,
|
||||||
typename quantity_point_like_traits<QP>::rep>;
|
typename quantity_point_like_traits<QP>::rep>;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<typename D, typename U, typename Rep>
|
template<typename O, typename U, typename Rep>
|
||||||
inline constexpr bool is_quantity_point<quantity_point<D, U, Rep>> = true;
|
inline constexpr bool is_quantity_point<quantity_point<O, U, Rep>> = true;
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
@@ -34,7 +34,7 @@ namespace units {
|
|||||||
/**
|
/**
|
||||||
* @brief A quantity point kind
|
* @brief A quantity point kind
|
||||||
*
|
*
|
||||||
* An absolute quantity kind with respect to zero (which represents some origin).
|
* An absolute quantity kind measured from an origin.
|
||||||
*
|
*
|
||||||
* @tparam PK the point kind of quantity point
|
* @tparam PK the point kind of quantity point
|
||||||
* @tparam U the measurement unit of the quantity point kind
|
* @tparam U the measurement unit of the quantity point kind
|
||||||
@@ -45,6 +45,7 @@ class quantity_point_kind {
|
|||||||
public:
|
public:
|
||||||
using point_kind_type = PK;
|
using point_kind_type = PK;
|
||||||
using kind_type = typename PK::base_kind;
|
using kind_type = typename PK::base_kind;
|
||||||
|
using origin = typename point_kind_type::origin;
|
||||||
using quantity_kind_type = quantity_kind<kind_type, U, Rep>;
|
using quantity_kind_type = quantity_kind<kind_type, U, Rep>;
|
||||||
using quantity_type = typename quantity_kind_type::quantity_type;
|
using quantity_type = typename quantity_kind_type::quantity_type;
|
||||||
using dimension = typename quantity_type::dimension;
|
using dimension = typename quantity_type::dimension;
|
||||||
@@ -60,32 +61,28 @@ public:
|
|||||||
quantity_point_kind(const quantity_point_kind&) = default;
|
quantity_point_kind(const quantity_point_kind&) = default;
|
||||||
quantity_point_kind(quantity_point_kind&&) = default;
|
quantity_point_kind(quantity_point_kind&&) = default;
|
||||||
|
|
||||||
template<safe_convertible_to_<rep> Value>
|
template<typename T>
|
||||||
requires std::is_constructible_v<quantity_kind_type, Value>
|
requires std::constructible_from<quantity_kind_type, T>
|
||||||
constexpr explicit quantity_point_kind(const Value& v) : qk_(v) {}
|
constexpr explicit quantity_point_kind(T&& t) : qk_(std::forward<T>(t)) {}
|
||||||
|
|
||||||
constexpr explicit quantity_point_kind(const quantity_type& q) : qk_{q} {}
|
constexpr explicit quantity_point_kind(const quantity_point<origin, U, Rep>& qp) : qk_(qp.relative()) {}
|
||||||
|
constexpr explicit quantity_point_kind(quantity_point<origin, U, Rep>&& qp) : qk_(std::move(qp).relative()) {}
|
||||||
template<QuantityLike Q>
|
|
||||||
requires std::is_constructible_v<quantity_type, Q>
|
|
||||||
constexpr explicit quantity_point_kind(const Q& q) : qk_{q} {}
|
|
||||||
|
|
||||||
template<QuantityPointLike QP>
|
template<QuantityPointLike QP>
|
||||||
requires std::is_constructible_v<quantity_point<dimension, U, Rep>, QP>
|
requires std::constructible_from<quantity_point<origin, U, Rep>, QP>
|
||||||
constexpr explicit quantity_point_kind(const QP& qp) : qk_{quantity_point_like_traits<QP>::relative(qp)} {}
|
constexpr explicit quantity_point_kind(const QP& qp) : qk_(quantity_point_like_traits<QP>::relative(qp)) {}
|
||||||
|
|
||||||
constexpr explicit quantity_point_kind(const quantity_point<dimension, U, Rep>& qp) : qk_{qp.relative()} {}
|
template<QuantityPointKindOf<point_kind_type> QPK2>
|
||||||
|
requires std::convertible_to<typename QPK2::quantity_kind_type, quantity_kind_type>
|
||||||
constexpr explicit quantity_point_kind(const quantity_kind_type& qk) : qk_{qk} {}
|
constexpr explicit(false) quantity_point_kind(const QPK2& qpk) : qk_(qpk.relative()) {}
|
||||||
|
|
||||||
template<QuantityPointKindEquivalentTo<quantity_point_kind> QPK2>
|
|
||||||
requires std::is_convertible_v<typename QPK2::quantity_kind_type, quantity_kind_type>
|
|
||||||
constexpr explicit(false) quantity_point_kind(const QPK2& qpk) : qk_{qpk.relative()} {}
|
|
||||||
|
|
||||||
quantity_point_kind& operator=(const quantity_point_kind&) = default;
|
quantity_point_kind& operator=(const quantity_point_kind&) = default;
|
||||||
quantity_point_kind& operator=(quantity_point_kind&&) = default;
|
quantity_point_kind& operator=(quantity_point_kind&&) = default;
|
||||||
|
|
||||||
[[nodiscard]] constexpr quantity_kind_type relative() const noexcept { return qk_; }
|
[[nodiscard]] constexpr quantity_kind_type& relative() & noexcept { return qk_; }
|
||||||
|
[[nodiscard]] constexpr const quantity_kind_type& relative() const & noexcept { return qk_; }
|
||||||
|
[[nodiscard]] constexpr quantity_kind_type&& relative() && noexcept { return std::move(qk_); }
|
||||||
|
[[nodiscard]] constexpr const quantity_kind_type&& relative() const && noexcept { return std::move(qk_); }
|
||||||
|
|
||||||
[[nodiscard]] static constexpr quantity_point_kind min() noexcept
|
[[nodiscard]] static constexpr quantity_point_kind min() noexcept
|
||||||
requires requires { quantity_kind_type::min(); }
|
requires requires { quantity_kind_type::min(); }
|
||||||
@@ -163,20 +160,21 @@ public:
|
|||||||
return units::quantity_point_kind(lhs.relative() - rhs);
|
return units::quantity_point_kind(lhs.relative() - rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr QuantityKind auto operator-(const quantity_point_kind& lhs, const quantity_point_kind& rhs)
|
template<QuantityPointKindOf<point_kind_type> QPK>
|
||||||
|
[[nodiscard]] friend constexpr QuantityKind auto operator-(const quantity_point_kind& lhs, const QPK& rhs)
|
||||||
requires requires(quantity_kind_type qk) { qk - qk; }
|
requires requires(quantity_kind_type qk) { qk - qk; }
|
||||||
{
|
{
|
||||||
return lhs.relative() - rhs.relative();
|
return lhs.relative() - rhs.relative();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantityPointKind QPK>
|
template<QuantityPointKindOf<point_kind_type> QPK>
|
||||||
requires std::three_way_comparable_with<quantity_kind_type, typename QPK::quantity_kind_type>
|
requires std::three_way_comparable_with<quantity_kind_type, typename QPK::quantity_kind_type>
|
||||||
[[nodiscard]] friend constexpr auto operator<=>(const quantity_point_kind& lhs, const QPK& rhs)
|
[[nodiscard]] friend constexpr auto operator<=>(const quantity_point_kind& lhs, const QPK& rhs)
|
||||||
{
|
{
|
||||||
return lhs.relative() <=> rhs.relative();
|
return lhs.relative() <=> rhs.relative();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantityPointKind QPK>
|
template<QuantityPointKindOf<point_kind_type> QPK>
|
||||||
requires std::equality_comparable_with<quantity_kind_type, typename QPK::quantity_kind_type>
|
requires std::equality_comparable_with<quantity_kind_type, typename QPK::quantity_kind_type>
|
||||||
[[nodiscard]] friend constexpr bool operator==(const quantity_point_kind& lhs, const QPK& rhs)
|
[[nodiscard]] friend constexpr bool operator==(const quantity_point_kind& lhs, const QPK& rhs)
|
||||||
{
|
{
|
||||||
|
@@ -22,11 +22,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/bits/deduced_symbol_text.h>
|
#include <units/bits/derived_symbol_text.h>
|
||||||
#include <units/bits/external/downcasting.h>
|
#include <units/bits/external/downcasting.h>
|
||||||
|
|
||||||
// IWYU pragma: begin_exports
|
// IWYU pragma: begin_exports
|
||||||
#include <units/bits/deduced_unit.h>
|
#include <units/bits/derived_unit.h>
|
||||||
#include <units/bits/external/fixed_string.h>
|
#include <units/bits/external/fixed_string.h>
|
||||||
#include <units/prefix.h>
|
#include <units/prefix.h>
|
||||||
#include <units/ratio.h>
|
#include <units/ratio.h>
|
||||||
@@ -155,37 +155,12 @@ struct prefixed_unit : downcast_dispatch<Child, scaled_unit<P::ratio * U::ratio,
|
|||||||
template<typename Child, DerivedDimension Dim, Unit U, Unit... URest>
|
template<typename Child, DerivedDimension Dim, Unit U, Unit... URest>
|
||||||
requires detail::same_scaled_units<typename Dim::recipe, U, URest...> &&
|
requires detail::same_scaled_units<typename Dim::recipe, U, URest...> &&
|
||||||
(U::is_named && (URest::is_named && ... && true))
|
(U::is_named && (URest::is_named && ... && true))
|
||||||
struct deduced_unit : downcast_dispatch<Child, detail::deduced_unit<Dim, U, URest...>> {
|
struct derived_unit : downcast_dispatch<Child, detail::derived_unit<Dim, U, URest...>> {
|
||||||
static constexpr bool is_named = false;
|
static constexpr bool is_named = false;
|
||||||
static constexpr auto symbol = detail::deduced_symbol_text<Dim, U, URest...>();
|
static constexpr auto symbol = detail::derived_symbol_text<Dim, U, URest...>();
|
||||||
using prefix_family = no_prefix;
|
using prefix_family = no_prefix;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A unit with a deduced ratio and symbol that can be used as a named unit for children
|
|
||||||
*
|
|
||||||
* Defines a new unit with a deduced ratio and symbol based on the recipe from the provided
|
|
||||||
* derived dimension. The number and order of provided units should match the recipe of the
|
|
||||||
* derived dimension. All of the units provided should also be a named ones so it is possible
|
|
||||||
* to create a deduced symbol text.
|
|
||||||
*
|
|
||||||
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
|
|
||||||
* @tparam Dim a derived dimension recipe to use for deduction
|
|
||||||
* @tparam U the unit of the first composite dimension from provided derived dimension's recipe
|
|
||||||
* @tparam URest the units for the rest of dimensions from the recipe
|
|
||||||
*/
|
|
||||||
template<typename Child, DerivedDimension Dim, Unit U, Unit... URest>
|
|
||||||
requires detail::same_scaled_units<typename Dim::recipe, U, URest...> &&
|
|
||||||
(U::is_named && (URest::is_named && ... && true))
|
|
||||||
// TODO - 'noble' is placeholder to sort of mean can pass its name on to other deduced units
|
|
||||||
struct noble_deduced_unit : downcast_dispatch<Child, detail::deduced_unit<Dim, U, URest...>> {
|
|
||||||
static constexpr bool is_named = true;
|
|
||||||
static constexpr auto symbol = detail::deduced_symbol_text<Dim, U, URest...>();
|
|
||||||
using prefix_family = no_prefix;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A named unit with a deduced ratio
|
* @brief A named unit with a deduced ratio
|
||||||
*
|
*
|
||||||
@@ -203,7 +178,7 @@ struct noble_deduced_unit : downcast_dispatch<Child, detail::deduced_unit<Dim, U
|
|||||||
*/
|
*/
|
||||||
template<typename Child, DerivedDimension Dim, basic_symbol_text Symbol, PrefixFamily PF, Unit U, Unit... URest>
|
template<typename Child, DerivedDimension Dim, basic_symbol_text Symbol, PrefixFamily PF, Unit U, Unit... URest>
|
||||||
requires detail::same_scaled_units<typename Dim::recipe, U, URest...>
|
requires detail::same_scaled_units<typename Dim::recipe, U, URest...>
|
||||||
struct named_deduced_unit : downcast_dispatch<Child, detail::deduced_unit<Dim, U, URest...>> {
|
struct named_derived_unit : downcast_dispatch<Child, detail::derived_unit<Dim, U, URest...>> {
|
||||||
static constexpr bool is_named = true;
|
static constexpr bool is_named = true;
|
||||||
static constexpr auto symbol = Symbol;
|
static constexpr auto symbol = Symbol;
|
||||||
using prefix_family = PF;
|
using prefix_family = PF;
|
||||||
|
@@ -50,7 +50,7 @@ using dim_modulation_rate = si::dim_frequency;
|
|||||||
template<UnitOf<dim_modulation_rate> U, Representation Rep = double>
|
template<UnitOf<dim_modulation_rate> U, Representation Rep = double>
|
||||||
using modulation_rate = quantity<dim_modulation_rate, U, Rep>;
|
using modulation_rate = quantity<dim_modulation_rate, U, Rep>;
|
||||||
|
|
||||||
#ifdef UNITS_LITERALS
|
#ifndef UNITS_NO_LITERALS
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
@@ -66,9 +66,9 @@ constexpr auto operator"" _q_YBd(unsigned long long l) { gsl_ExpectsAudit(std::i
|
|||||||
|
|
||||||
} // namespace literals
|
} // namespace literals
|
||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_NO_LITERALS
|
||||||
|
|
||||||
#ifdef UNITS_REFERENCES
|
#ifndef UNITS_NO_REFERENCES
|
||||||
|
|
||||||
namespace modulation_rate_references {
|
namespace modulation_rate_references {
|
||||||
|
|
||||||
@@ -90,11 +90,11 @@ using namespace modulation_rate_references;
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
#endif // UNITS_REFERENCES
|
#endif // UNITS_NO_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::iec80000
|
} // namespace units::isq::iec80000
|
||||||
|
|
||||||
#ifdef UNITS_ALIASES
|
#ifndef UNITS_NO_ALIASES
|
||||||
|
|
||||||
namespace units::aliases::isq::iec80000::inline modulation_rate {
|
namespace units::aliases::isq::iec80000::inline modulation_rate {
|
||||||
|
|
||||||
@@ -110,4 +110,4 @@ template<Representation Rep = double> using YBd = units::isq::iec80000::modulati
|
|||||||
|
|
||||||
} // namespace units::aliases::isq::iec80000::inline modulation_rate
|
} // namespace units::aliases::isq::iec80000::inline modulation_rate
|
||||||
|
|
||||||
#endif // UNITS_ALIASES
|
#endif // UNITS_NO_ALIASES
|
||||||
|
@@ -79,7 +79,7 @@ concept StorageCapacity = QuantityOf<T, dim_storage_capacity>;
|
|||||||
template<UnitOf<dim_storage_capacity> U, Representation Rep = double>
|
template<UnitOf<dim_storage_capacity> U, Representation Rep = double>
|
||||||
using storage_capacity = quantity<dim_storage_capacity, U, Rep>;
|
using storage_capacity = quantity<dim_storage_capacity, U, Rep>;
|
||||||
|
|
||||||
#ifdef UNITS_LITERALS
|
#ifndef UNITS_NO_LITERALS
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
@@ -123,9 +123,9 @@ constexpr auto operator"" _q_PiB(unsigned long long l) { gsl_ExpectsAudit(std::i
|
|||||||
|
|
||||||
} // namespace literals
|
} // namespace literals
|
||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_NO_LITERALS
|
||||||
|
|
||||||
#ifdef UNITS_REFERENCES
|
#ifndef UNITS_NO_REFERENCES
|
||||||
|
|
||||||
namespace storage_capacity_references {
|
namespace storage_capacity_references {
|
||||||
|
|
||||||
@@ -175,11 +175,11 @@ using namespace storage_capacity_references;
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
#endif // UNITS_REFERENCES
|
#endif // UNITS_NO_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::iec80000
|
} // namespace units::isq::iec80000
|
||||||
|
|
||||||
#ifdef UNITS_ALIASES
|
#ifndef UNITS_NO_ALIASES
|
||||||
|
|
||||||
namespace units::aliases::isq::iec80000::inline storage_capacity {
|
namespace units::aliases::isq::iec80000::inline storage_capacity {
|
||||||
|
|
||||||
@@ -223,4 +223,4 @@ template<Representation Rep = double> using PiB = units::isq::iec80000::storage_
|
|||||||
|
|
||||||
} // namespace units::aliases::isq::iec80000::inline storage_capacity
|
} // namespace units::aliases::isq::iec80000::inline storage_capacity
|
||||||
|
|
||||||
#endif // UNITS_ALIASES
|
#endif // UNITS_NO_ALIASES
|
||||||
|
@@ -43,7 +43,7 @@ concept TrafficIntensity = QuantityOf<T, dim_traffic_intensity>;
|
|||||||
template<UnitOf<dim_traffic_intensity> U, Representation Rep = double>
|
template<UnitOf<dim_traffic_intensity> U, Representation Rep = double>
|
||||||
using traffic_intensity = quantity<dim_traffic_intensity, U, Rep>;
|
using traffic_intensity = quantity<dim_traffic_intensity, U, Rep>;
|
||||||
|
|
||||||
#ifdef UNITS_LITERALS
|
#ifndef UNITS_NO_LITERALS
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
@@ -51,9 +51,9 @@ constexpr auto operator"" _q_E(unsigned long long l) { gsl_ExpectsAudit(std::in_
|
|||||||
|
|
||||||
} // namespace literals
|
} // namespace literals
|
||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_NO_LITERALS
|
||||||
|
|
||||||
#ifdef UNITS_REFERENCES
|
#ifndef UNITS_NO_REFERENCES
|
||||||
|
|
||||||
namespace traffic_intensity_references {
|
namespace traffic_intensity_references {
|
||||||
|
|
||||||
@@ -67,11 +67,11 @@ using namespace traffic_intensity_references;
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
#endif // UNITS_REFERENCES
|
#endif // UNITS_NO_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::iec80000
|
} // namespace units::isq::iec80000
|
||||||
|
|
||||||
#ifdef UNITS_ALIASES
|
#ifndef UNITS_NO_ALIASES
|
||||||
|
|
||||||
namespace units::aliases::isq::iec80000::inline traffic_intensity {
|
namespace units::aliases::isq::iec80000::inline traffic_intensity {
|
||||||
|
|
||||||
@@ -79,4 +79,4 @@ template<Representation Rep = double> using E = units::isq::iec80000::traffic_in
|
|||||||
|
|
||||||
} // namespace units::aliases::isq::iec80000::inline traffic_intensity
|
} // namespace units::aliases::isq::iec80000::inline traffic_intensity
|
||||||
|
|
||||||
#endif // UNITS_ALIASES
|
#endif // UNITS_NO_ALIASES
|
||||||
|
@@ -37,14 +37,14 @@ namespace units::isq::iec80000 {
|
|||||||
struct byte_per_second : unit<byte_per_second> {};
|
struct byte_per_second : unit<byte_per_second> {};
|
||||||
struct dim_transfer_rate : derived_dimension<dim_transfer_rate, byte_per_second, exponent<dim_storage_capacity, 1>, exponent<si::dim_time, -1>> {};
|
struct dim_transfer_rate : derived_dimension<dim_transfer_rate, byte_per_second, exponent<dim_storage_capacity, 1>, exponent<si::dim_time, -1>> {};
|
||||||
|
|
||||||
struct kilobyte_per_second : deduced_unit<kilobyte_per_second, dim_transfer_rate, kilobyte, si::second> {};
|
struct kilobyte_per_second : derived_unit<kilobyte_per_second, dim_transfer_rate, kilobyte, si::second> {};
|
||||||
struct megabyte_per_second : deduced_unit<megabyte_per_second, dim_transfer_rate, megabyte, si::second> {};
|
struct megabyte_per_second : derived_unit<megabyte_per_second, dim_transfer_rate, megabyte, si::second> {};
|
||||||
struct gigabyte_per_second : deduced_unit<gigabyte_per_second, dim_transfer_rate, gigabyte, si::second> {};
|
struct gigabyte_per_second : derived_unit<gigabyte_per_second, dim_transfer_rate, gigabyte, si::second> {};
|
||||||
struct terabyte_per_second : deduced_unit<terabyte_per_second, dim_transfer_rate, terabyte, si::second> {};
|
struct terabyte_per_second : derived_unit<terabyte_per_second, dim_transfer_rate, terabyte, si::second> {};
|
||||||
struct petabyte_per_second : deduced_unit<petabyte_per_second, dim_transfer_rate, petabyte, si::second> {};
|
struct petabyte_per_second : derived_unit<petabyte_per_second, dim_transfer_rate, petabyte, si::second> {};
|
||||||
struct exabyte_per_second : deduced_unit<exabyte_per_second, dim_transfer_rate, exabyte, si::second> {};
|
struct exabyte_per_second : derived_unit<exabyte_per_second, dim_transfer_rate, exabyte, si::second> {};
|
||||||
struct zettabyte_per_second : deduced_unit<zettabyte_per_second, dim_transfer_rate, zettabyte, si::second> {};
|
struct zettabyte_per_second : derived_unit<zettabyte_per_second, dim_transfer_rate, zettabyte, si::second> {};
|
||||||
struct yottabyte_per_second : deduced_unit<yottabyte_per_second, dim_transfer_rate, yottabyte, si::second> {};
|
struct yottabyte_per_second : derived_unit<yottabyte_per_second, dim_transfer_rate, yottabyte, si::second> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept TransferRate = QuantityOf<T, dim_transfer_rate>;
|
concept TransferRate = QuantityOf<T, dim_transfer_rate>;
|
||||||
@@ -52,7 +52,7 @@ concept TransferRate = QuantityOf<T, dim_transfer_rate>;
|
|||||||
template<UnitOf<dim_transfer_rate> U, Representation Rep = double>
|
template<UnitOf<dim_transfer_rate> U, Representation Rep = double>
|
||||||
using transfer_rate = quantity<dim_transfer_rate, U, Rep>;
|
using transfer_rate = quantity<dim_transfer_rate, U, Rep>;
|
||||||
|
|
||||||
#ifdef UNITS_LITERALS
|
#ifndef UNITS_NO_LITERALS
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
@@ -68,11 +68,11 @@ constexpr auto operator"" _q_YB_per_s(unsigned long long l) { gsl_ExpectsAudit(s
|
|||||||
|
|
||||||
} // namespace literals
|
} // namespace literals
|
||||||
|
|
||||||
#endif // UNITS_LITERALS
|
#endif // UNITS_NO_LITERALS
|
||||||
|
|
||||||
} // namespace units::isq::iec80000
|
} // namespace units::isq::iec80000
|
||||||
|
|
||||||
#ifdef UNITS_ALIASES
|
#ifndef UNITS_NO_ALIASES
|
||||||
|
|
||||||
namespace units::aliases::isq::iec80000::inline transfer_rate {
|
namespace units::aliases::isq::iec80000::inline transfer_rate {
|
||||||
|
|
||||||
@@ -88,4 +88,4 @@ template<Representation Rep = double> using YB_per_s = units::isq::iec80000::tra
|
|||||||
|
|
||||||
} // namespace units::aliases::isq::iec80000::inline transfer_rate
|
} // namespace units::aliases::isq::iec80000::inline transfer_rate
|
||||||
|
|
||||||
#endif // UNITS_ALIASES
|
#endif // UNITS_NO_ALIASES
|
||||||
|
@@ -40,7 +40,7 @@ struct dim_acceleration : isq::dim_acceleration<dim_acceleration, gigaelectronvo
|
|||||||
template<UnitOf<dim_acceleration> U, Representation Rep = double>
|
template<UnitOf<dim_acceleration> U, Representation Rep = double>
|
||||||
using acceleration = quantity<dim_acceleration, U, Rep>;
|
using acceleration = quantity<dim_acceleration, U, Rep>;
|
||||||
|
|
||||||
#ifdef UNITS_REFERENCES
|
#ifndef UNITS_NO_REFERENCES
|
||||||
|
|
||||||
namespace acceleration_references {
|
namespace acceleration_references {
|
||||||
|
|
||||||
@@ -54,11 +54,11 @@ using namespace acceleration_references;
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
#endif // UNITS_REFERENCES
|
#endif // UNITS_NO_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::natural
|
} // namespace units::isq::natural
|
||||||
|
|
||||||
#ifdef UNITS_ALIASES
|
#ifndef UNITS_NO_ALIASES
|
||||||
|
|
||||||
namespace units::aliases::isq::natural::inline acceleration {
|
namespace units::aliases::isq::natural::inline acceleration {
|
||||||
|
|
||||||
@@ -66,4 +66,4 @@ template<Representation Rep = double> using GeV = units::isq::natural::accelerat
|
|||||||
|
|
||||||
} // namespace units::aliases::isq::natural::inline acceleration
|
} // namespace units::aliases::isq::natural::inline acceleration
|
||||||
|
|
||||||
#endif // UNITS_ALIASES
|
#endif // UNITS_NO_ALIASES
|
||||||
|
@@ -40,7 +40,7 @@ struct dim_energy : isq::dim_energy<dim_energy, gigaelectronvolt, dim_force, dim
|
|||||||
template<UnitOf<dim_energy> U, Representation Rep = double>
|
template<UnitOf<dim_energy> U, Representation Rep = double>
|
||||||
using energy = quantity<dim_energy, U, Rep>;
|
using energy = quantity<dim_energy, U, Rep>;
|
||||||
|
|
||||||
#ifdef UNITS_REFERENCES
|
#ifndef UNITS_NO_REFERENCES
|
||||||
|
|
||||||
namespace energy_references {
|
namespace energy_references {
|
||||||
|
|
||||||
@@ -54,11 +54,11 @@ using namespace energy_references;
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
#endif // UNITS_REFERENCES
|
#endif // UNITS_NO_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::natural
|
} // namespace units::isq::natural
|
||||||
|
|
||||||
#ifdef UNITS_ALIASES
|
#ifndef UNITS_NO_ALIASES
|
||||||
|
|
||||||
namespace units::aliases::isq::natural::inline energy {
|
namespace units::aliases::isq::natural::inline energy {
|
||||||
|
|
||||||
@@ -66,4 +66,4 @@ template<Representation Rep = double> using GeV = units::isq::natural::energy<un
|
|||||||
|
|
||||||
} // namespace units::aliases::isq::natural::inline energy
|
} // namespace units::aliases::isq::natural::inline energy
|
||||||
|
|
||||||
#endif // UNITS_ALIASES
|
#endif // UNITS_NO_ALIASES
|
||||||
|
@@ -40,7 +40,7 @@ struct dim_force : isq::dim_force<dim_force, square_gigaelectronvolt, dim_mass,
|
|||||||
template<UnitOf<dim_force> U, Representation Rep = double>
|
template<UnitOf<dim_force> U, Representation Rep = double>
|
||||||
using force = quantity<dim_force, U, Rep>;
|
using force = quantity<dim_force, U, Rep>;
|
||||||
|
|
||||||
#ifdef UNITS_REFERENCES
|
#ifndef UNITS_NO_REFERENCES
|
||||||
|
|
||||||
namespace force_references {
|
namespace force_references {
|
||||||
|
|
||||||
@@ -54,11 +54,11 @@ using namespace force_references;
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
#endif // UNITS_REFERENCES
|
#endif // UNITS_NO_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::natural
|
} // namespace units::isq::natural
|
||||||
|
|
||||||
#ifdef UNITS_ALIASES
|
#ifndef UNITS_NO_ALIASES
|
||||||
|
|
||||||
namespace units::aliases::isq::natural::inline force {
|
namespace units::aliases::isq::natural::inline force {
|
||||||
|
|
||||||
@@ -66,4 +66,4 @@ template<Representation Rep = double> using GeV2 = units::isq::natural::force<un
|
|||||||
|
|
||||||
} // namespace units::aliases::isq::natural::inline force
|
} // namespace units::aliases::isq::natural::inline force
|
||||||
|
|
||||||
#endif // UNITS_ALIASES
|
#endif // UNITS_NO_ALIASES
|
||||||
|
@@ -37,7 +37,7 @@ struct dim_length : isq::dim_length<inverted_gigaelectronvolt> {};
|
|||||||
template<UnitOf<dim_length> U, Representation Rep = double>
|
template<UnitOf<dim_length> U, Representation Rep = double>
|
||||||
using length = quantity<dim_length, U, Rep>;
|
using length = quantity<dim_length, U, Rep>;
|
||||||
|
|
||||||
#ifdef UNITS_REFERENCES
|
#ifndef UNITS_NO_REFERENCES
|
||||||
|
|
||||||
namespace length_references {
|
namespace length_references {
|
||||||
|
|
||||||
@@ -51,11 +51,11 @@ using namespace length_references;
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
#endif // UNITS_REFERENCES
|
#endif // UNITS_NO_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::natural
|
} // namespace units::isq::natural
|
||||||
|
|
||||||
#ifdef UNITS_ALIASES
|
#ifndef UNITS_NO_ALIASES
|
||||||
|
|
||||||
namespace units::aliases::isq::natural::inline length {
|
namespace units::aliases::isq::natural::inline length {
|
||||||
|
|
||||||
@@ -63,4 +63,4 @@ template<Representation Rep = double> using inv_GeV = units::isq::natural::lengt
|
|||||||
|
|
||||||
} // namespace units::aliases::isq::natural::inline length
|
} // namespace units::aliases::isq::natural::inline length
|
||||||
|
|
||||||
#endif // UNITS_ALIASES
|
#endif // UNITS_NO_ALIASES
|
||||||
|
@@ -37,7 +37,7 @@ struct dim_mass : isq::dim_mass<gigaelectronvolt> {};
|
|||||||
template<UnitOf<dim_mass> U, Representation Rep = double>
|
template<UnitOf<dim_mass> U, Representation Rep = double>
|
||||||
using mass = quantity<dim_mass, U, Rep>;
|
using mass = quantity<dim_mass, U, Rep>;
|
||||||
|
|
||||||
#ifdef UNITS_REFERENCES
|
#ifndef UNITS_NO_REFERENCES
|
||||||
|
|
||||||
namespace mass_references {
|
namespace mass_references {
|
||||||
|
|
||||||
@@ -51,11 +51,11 @@ using namespace mass_references;
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
#endif // UNITS_REFERENCES
|
#endif // UNITS_NO_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::natural
|
} // namespace units::isq::natural
|
||||||
|
|
||||||
#ifdef UNITS_ALIASES
|
#ifndef UNITS_NO_ALIASES
|
||||||
|
|
||||||
namespace units::aliases::isq::natural::inline mass {
|
namespace units::aliases::isq::natural::inline mass {
|
||||||
|
|
||||||
@@ -63,4 +63,4 @@ template<Representation Rep = double> using GeV = units::isq::natural::mass<unit
|
|||||||
|
|
||||||
} // namespace units::aliases::isq::natural::inline mass
|
} // namespace units::aliases::isq::natural::inline mass
|
||||||
|
|
||||||
#endif // UNITS_ALIASES
|
#endif // UNITS_NO_ALIASES
|
||||||
|
@@ -40,7 +40,7 @@ struct dim_momentum : isq::dim_momentum<dim_momentum, gigaelectronvolt, dim_mass
|
|||||||
template<UnitOf<dim_momentum> U, Representation Rep = double>
|
template<UnitOf<dim_momentum> U, Representation Rep = double>
|
||||||
using momentum = quantity<dim_momentum, U, Rep>;
|
using momentum = quantity<dim_momentum, U, Rep>;
|
||||||
|
|
||||||
#ifdef UNITS_REFERENCES
|
#ifndef UNITS_NO_REFERENCES
|
||||||
|
|
||||||
namespace momentum_references {
|
namespace momentum_references {
|
||||||
|
|
||||||
@@ -54,11 +54,11 @@ using namespace momentum_references;
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
#endif // UNITS_REFERENCES
|
#endif // UNITS_NO_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::natural
|
} // namespace units::isq::natural
|
||||||
|
|
||||||
#ifdef UNITS_ALIASES
|
#ifndef UNITS_NO_ALIASES
|
||||||
|
|
||||||
namespace units::aliases::isq::natural::inline momentum {
|
namespace units::aliases::isq::natural::inline momentum {
|
||||||
|
|
||||||
@@ -66,4 +66,4 @@ template<Representation Rep = double> using GeV = units::isq::natural::momentum<
|
|||||||
|
|
||||||
} // namespace units::aliases::isq::natural::inline momentum
|
} // namespace units::aliases::isq::natural::inline momentum
|
||||||
|
|
||||||
#endif // UNITS_ALIASES
|
#endif // UNITS_NO_ALIASES
|
||||||
|
@@ -37,7 +37,7 @@ struct dim_time : isq::dim_time<inverted_gigaelectronvolt> {};
|
|||||||
template<UnitOf<dim_time> U, Representation Rep = double>
|
template<UnitOf<dim_time> U, Representation Rep = double>
|
||||||
using time = quantity<dim_time, U, Rep>;
|
using time = quantity<dim_time, U, Rep>;
|
||||||
|
|
||||||
#ifdef UNITS_REFERENCES
|
#ifndef UNITS_NO_REFERENCES
|
||||||
|
|
||||||
namespace time_references {
|
namespace time_references {
|
||||||
|
|
||||||
@@ -51,11 +51,11 @@ using namespace time_references;
|
|||||||
|
|
||||||
} // namespace references
|
} // namespace references
|
||||||
|
|
||||||
#endif // UNITS_REFERENCES
|
#endif // UNITS_NO_REFERENCES
|
||||||
|
|
||||||
} // namespace units::isq::natural
|
} // namespace units::isq::natural
|
||||||
|
|
||||||
#ifdef UNITS_ALIASES
|
#ifndef UNITS_NO_ALIASES
|
||||||
|
|
||||||
namespace units::aliases::isq::natural::inline time {
|
namespace units::aliases::isq::natural::inline time {
|
||||||
|
|
||||||
@@ -63,4 +63,4 @@ template<Representation Rep = double> using inv_GeV = units::isq::natural::time<
|
|||||||
|
|
||||||
} // namespace units::aliases::isq::natural::inline time
|
} // namespace units::aliases::isq::natural::inline time
|
||||||
|
|
||||||
#endif // UNITS_ALIASES
|
#endif // UNITS_NO_ALIASES
|
||||||
|
@@ -28,8 +28,11 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_absorbed_dose;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_energy> E, DimensionOfT<dim_mass> M>
|
template<typename Child, Unit U, DimensionOfT<dim_energy> E, DimensionOfT<dim_mass> M>
|
||||||
struct dim_absorbed_dose : derived_dimension<Child, U, exponent<E, 1>, exponent<M, -1>> {};
|
struct dim_absorbed_dose<Child, U, E, M> : derived_dimension<Child, U, exponent<E, 1>, exponent<M, -1>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept AbsorbedDose = QuantityOfT<T, dim_absorbed_dose>;
|
concept AbsorbedDose = QuantityOfT<T, dim_absorbed_dose>;
|
||||||
|
@@ -28,8 +28,11 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_acceleration;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_length> L, DimensionOfT<dim_time> T>
|
template<typename Child, Unit U, DimensionOfT<dim_length> L, DimensionOfT<dim_time> T>
|
||||||
struct dim_acceleration : derived_dimension<Child, U, exponent<L, 1>, exponent<T, -2>> {};
|
struct dim_acceleration<Child, U, L, T> : derived_dimension<Child, U, exponent<L, 1>, exponent<T, -2>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept Acceleration = QuantityOfT<T, dim_acceleration>;
|
concept Acceleration = QuantityOfT<T, dim_acceleration>;
|
||||||
|
@@ -28,8 +28,11 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_angular_velocity;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_angle> A, DimensionOfT<dim_time> T>
|
template<typename Child, Unit U, DimensionOfT<dim_angle> A, DimensionOfT<dim_time> T>
|
||||||
struct dim_angular_velocity : derived_dimension<Child, U, exponent<A, 1>, exponent<T, -1>> {};
|
struct dim_angular_velocity<Child, U, A, T> : derived_dimension<Child, U, exponent<A, 1>, exponent<T, -1>> {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept AngularVelocity = QuantityOfT<T, dim_angular_velocity>;
|
concept AngularVelocity = QuantityOfT<T, dim_angular_velocity>;
|
||||||
|
@@ -27,8 +27,11 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_area;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_length> L>
|
template<typename Child, Unit U, DimensionOfT<dim_length> L>
|
||||||
struct dim_area : derived_dimension<Child, U, exponent<L, 2>> {};
|
struct dim_area<Child, U, L> : derived_dimension<Child, U, exponent<L, 2>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept Area = QuantityOfT<T, dim_area>;
|
concept Area = QuantityOfT<T, dim_area>;
|
||||||
|
@@ -28,8 +28,11 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_capacitance;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_electric_charge> C, DimensionOfT<dim_voltage> V>
|
template<typename Child, Unit U, DimensionOfT<dim_electric_charge> C, DimensionOfT<dim_voltage> V>
|
||||||
struct dim_capacitance : derived_dimension<Child, U, exponent<C, 1>, exponent<V, -1>> {};
|
struct dim_capacitance<Child, U, C, V> : derived_dimension<Child, U, exponent<C, 1>, exponent<V, -1>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept Capacitance = QuantityOfT<T, dim_capacitance>;
|
concept Capacitance = QuantityOfT<T, dim_capacitance>;
|
||||||
|
@@ -28,8 +28,11 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_catalytic_activity;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_time> T, DimensionOfT<dim_amount_of_substance> M>
|
template<typename Child, Unit U, DimensionOfT<dim_time> T, DimensionOfT<dim_amount_of_substance> M>
|
||||||
struct dim_catalytic_activity : derived_dimension<Child, U, exponent<T, -1>, exponent<M, 1>> {};
|
struct dim_catalytic_activity<Child, U, T, M> : derived_dimension<Child, U, exponent<T, -1>, exponent<M, 1>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept CatalyticActivity = QuantityOfT<T, dim_catalytic_activity>;
|
concept CatalyticActivity = QuantityOfT<T, dim_catalytic_activity>;
|
||||||
|
@@ -28,11 +28,17 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_electric_charge> Q, DimensionOfT<dim_length> L>
|
template<typename Child, Unit U, typename...>
|
||||||
struct dim_charge_density : derived_dimension<Child, U, exponent<Q, 1>, exponent<L, -3>> {};
|
struct dim_charge_density;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_electric_charge> Q, DimensionOfT<dim_length> L>
|
template<typename Child, Unit U, DimensionOfT<dim_electric_charge> Q, DimensionOfT<dim_length> L>
|
||||||
struct dim_surface_charge_density : derived_dimension<Child, U, exponent<Q, 1>, exponent<L, -2>> {};
|
struct dim_charge_density<Child, U, Q, L> : derived_dimension<Child, U, exponent<Q, 1>, exponent<L, -3>> {};
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_surface_charge_density;
|
||||||
|
|
||||||
|
template<typename Child, Unit U, DimensionOfT<dim_electric_charge> Q, DimensionOfT<dim_length> L>
|
||||||
|
struct dim_surface_charge_density<Child, U, Q, L> : derived_dimension<Child, U, exponent<Q, 1>, exponent<L, -2>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept ChargeDensity = QuantityOfT<T, dim_charge_density>;
|
concept ChargeDensity = QuantityOfT<T, dim_charge_density>;
|
||||||
|
@@ -28,8 +28,11 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_concentration;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_amount_of_substance> M, DimensionOfT<dim_length> L>
|
template<typename Child, Unit U, DimensionOfT<dim_amount_of_substance> M, DimensionOfT<dim_length> L>
|
||||||
struct dim_concentration : derived_dimension<Child, U, exponent<M, 1>, exponent<L, -3>> {};
|
struct dim_concentration<Child, U, M, L> : derived_dimension<Child, U, exponent<M, 1>, exponent<L, -3>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept Concentration = QuantityOfT<T, dim_concentration>;
|
concept Concentration = QuantityOfT<T, dim_concentration>;
|
||||||
|
@@ -27,8 +27,11 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_conductance;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_resistance> R>
|
template<typename Child, Unit U, DimensionOfT<dim_resistance> R>
|
||||||
struct dim_conductance : derived_dimension<Child, U, exponent<R, -1>> {};
|
struct dim_conductance<Child, U, R> : derived_dimension<Child, U, exponent<R, -1>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept Conductance = QuantityOfT<T, dim_conductance>;
|
concept Conductance = QuantityOfT<T, dim_conductance>;
|
||||||
|
@@ -28,8 +28,11 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_current_density;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_electric_current> I, DimensionOfT<dim_length> L>
|
template<typename Child, Unit U, DimensionOfT<dim_electric_current> I, DimensionOfT<dim_length> L>
|
||||||
struct dim_current_density : derived_dimension<Child, U, exponent<I, 1>, exponent<L, -2>> {};
|
struct dim_current_density<Child, U, I, L> : derived_dimension<Child, U, exponent<I, 1>, exponent<L, -2>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept CurrentDensity = QuantityOfT<T, dim_current_density>;
|
concept CurrentDensity = QuantityOfT<T, dim_current_density>;
|
||||||
|
@@ -28,8 +28,11 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_density;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_mass> M, DimensionOfT<dim_length> L>
|
template<typename Child, Unit U, DimensionOfT<dim_mass> M, DimensionOfT<dim_length> L>
|
||||||
struct dim_density : derived_dimension<Child, U, exponent<M, 1>, exponent<L, -3>> {};
|
struct dim_density<Child, U, M, L> : derived_dimension<Child, U, exponent<M, 1>, exponent<L, -3>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept Density = QuantityOfT<T, dim_density>;
|
concept Density = QuantityOfT<T, dim_density>;
|
||||||
|
@@ -28,8 +28,11 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_dynamic_viscosity;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_pressure> P, DimensionOfT<dim_time> T>
|
template<typename Child, Unit U, DimensionOfT<dim_pressure> P, DimensionOfT<dim_time> T>
|
||||||
struct dim_dynamic_viscosity : derived_dimension<Child, U, exponent<P, 1>, exponent<T, 1>> {};
|
struct dim_dynamic_viscosity<Child, U, P, T> : derived_dimension<Child, U, exponent<P, 1>, exponent<T, 1>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept DynamicViscosity = QuantityOfT<T, dim_dynamic_viscosity>;
|
concept DynamicViscosity = QuantityOfT<T, dim_dynamic_viscosity>;
|
||||||
|
@@ -28,8 +28,11 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_electric_charge;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_time> T, DimensionOfT<dim_electric_current> C>
|
template<typename Child, Unit U, DimensionOfT<dim_time> T, DimensionOfT<dim_electric_current> C>
|
||||||
struct dim_electric_charge : derived_dimension<Child, U, exponent<T, 1>, exponent<C, 1>> {};
|
struct dim_electric_charge<Child, U, T, C> : derived_dimension<Child, U, exponent<T, 1>, exponent<C, 1>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept ElectricCharge = QuantityOfT<T, dim_electric_charge>;
|
concept ElectricCharge = QuantityOfT<T, dim_electric_charge>;
|
||||||
|
@@ -28,8 +28,11 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_electric_field_strength;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_voltage> V, DimensionOfT<dim_length> L>
|
template<typename Child, Unit U, DimensionOfT<dim_voltage> V, DimensionOfT<dim_length> L>
|
||||||
struct dim_electric_field_strength : derived_dimension<Child, U, exponent<V, 1>, exponent<L, -1>> {};
|
struct dim_electric_field_strength<Child, U, V, L> : derived_dimension<Child, U, exponent<V, 1>, exponent<L, -1>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept ElectricFieldStrength = QuantityOfT<T, dim_electric_field_strength>;
|
concept ElectricFieldStrength = QuantityOfT<T, dim_electric_field_strength>;
|
||||||
|
@@ -28,8 +28,14 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_energy;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_force> F, DimensionOfT<dim_length> L>
|
template<typename Child, Unit U, DimensionOfT<dim_force> F, DimensionOfT<dim_length> L>
|
||||||
struct dim_energy : derived_dimension<Child, U, exponent<F, 1>, exponent<L, 1>> {};
|
struct dim_energy<Child, U, F, L> : derived_dimension<Child, U, exponent<F, 1>, exponent<L, 1>> {};
|
||||||
|
|
||||||
|
template<typename Child, Unit U, DimensionOfT<dim_length> L, DimensionOfT<dim_force> F>
|
||||||
|
struct dim_energy<Child, U, L, F> : derived_dimension<Child, U, exponent<L, 1>, exponent<F, 1>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept Energy = QuantityOfT<T, dim_energy>;
|
concept Energy = QuantityOfT<T, dim_energy>;
|
||||||
|
@@ -28,8 +28,11 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_energy_density;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_energy> E, DimensionOfT<dim_volume> V>
|
template<typename Child, Unit U, DimensionOfT<dim_energy> E, DimensionOfT<dim_volume> V>
|
||||||
struct dim_energy_density : derived_dimension<Child, U, exponent<E, 1>, exponent<V, -1>> {};
|
struct dim_energy_density<Child, U, E, V> : derived_dimension<Child, U, exponent<E, 1>, exponent<V, -1>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept EnergyDensity = QuantityOfT<T, dim_energy_density>;
|
concept EnergyDensity = QuantityOfT<T, dim_energy_density>;
|
||||||
|
@@ -28,8 +28,11 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_force;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_mass> M, DimensionOfT<dim_acceleration> A>
|
template<typename Child, Unit U, DimensionOfT<dim_mass> M, DimensionOfT<dim_acceleration> A>
|
||||||
struct dim_force : derived_dimension<Child, U, exponent<M, 1>, exponent<A, 1>> {};
|
struct dim_force<Child, U, M, A> : derived_dimension<Child, U, exponent<M, 1>, exponent<A, 1>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept Force = QuantityOfT<T, dim_force>;
|
concept Force = QuantityOfT<T, dim_force>;
|
||||||
|
@@ -27,8 +27,11 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_frequency;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_time> T>
|
template<typename Child, Unit U, DimensionOfT<dim_time> T>
|
||||||
struct dim_frequency : derived_dimension<Child, U, exponent<T, -1>> {};
|
struct dim_frequency<Child, U, T> : derived_dimension<Child, U, exponent<T, -1>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept Frequency = QuantityOfT<T, dim_frequency>;
|
concept Frequency = QuantityOfT<T, dim_frequency>;
|
||||||
|
@@ -30,14 +30,23 @@
|
|||||||
|
|
||||||
namespace units::isq {
|
namespace units::isq {
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_heat_capacity;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_energy> E, DimensionOfT<dim_thermodynamic_temperature> T>
|
template<typename Child, Unit U, DimensionOfT<dim_energy> E, DimensionOfT<dim_thermodynamic_temperature> T>
|
||||||
struct dim_heat_capacity : derived_dimension<Child, U, exponent<E, 1>, exponent<T, -1>> {};
|
struct dim_heat_capacity<Child, U, E, T> : derived_dimension<Child, U, exponent<E, 1>, exponent<T, -1>> {};
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_specific_heat_capacity;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_heat_capacity> C, DimensionOfT<dim_mass> M>
|
template<typename Child, Unit U, DimensionOfT<dim_heat_capacity> C, DimensionOfT<dim_mass> M>
|
||||||
struct dim_specific_heat_capacity : derived_dimension<Child, U, exponent<C, 1>, exponent<M, -1>> {};
|
struct dim_specific_heat_capacity<Child, U, C, M> : derived_dimension<Child, U, exponent<C, 1>, exponent<M, -1>> {};
|
||||||
|
|
||||||
|
template<typename Child, Unit U, typename...>
|
||||||
|
struct dim_molar_heat_capacity;
|
||||||
|
|
||||||
template<typename Child, Unit U, DimensionOfT<dim_heat_capacity> C, DimensionOfT<dim_amount_of_substance> M>
|
template<typename Child, Unit U, DimensionOfT<dim_heat_capacity> C, DimensionOfT<dim_amount_of_substance> M>
|
||||||
struct dim_molar_heat_capacity : derived_dimension<Child, U, exponent<C, 1>, exponent<M, -1>> {};
|
struct dim_molar_heat_capacity<Child, U, C, M> : derived_dimension<Child, U, exponent<C, 1>, exponent<M, -1>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept HeatCapacity = QuantityOfT<T, dim_heat_capacity>;
|
concept HeatCapacity = QuantityOfT<T, dim_heat_capacity>;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user