Merge branch 'mpusz:master' into master

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

View File

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

View File

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

View File

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

View File

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

View File

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

1
.gitignore vendored
View File

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

View File

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

View File

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

View File

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

221
cmake/ccache.cmake Normal file
View File

@@ -0,0 +1,221 @@
# The MIT License (MIT)
#
# Copyright (c) 2017 Mateusz Pusz
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.4)
macro(_enable_ccache_failed)
if(NOT _enable_ccache_QUIET)
message(STATUS "Enabling ccache - failed")
endif()
return()
endmacro()
#
# enable_ccache([PROGRAM] # ccache by default
# [QUIET] [REQUIRED]
# [MODE DIRECT_PREPROCESSOR|DIRECT_DEPEND|PREPROCESSOR|DEPEND] # DIRECT_PREPROCESSOR by default
# [BASE_DIR dir]
# [ACCOUNT_FOR_COMPILE_TIME_HEADER_CHANGES]
# [ACCOUNT_FOR_PCH]
# [ACCOUNT_FOR_MODULES]
# [PREFIXES prefixes...]
# )
#
# BASE_DIR
# Set this option to ${CMAKE_BINARY_DIR} if you use FetchContent a lot for many projects with the same build options.
# Otherwise, if most of the sources come from the project itself then the default ${CMAKE_SOURCE_DIR} may be
# a better choice.
#
# ACCOUNT_FOR_COMPILE_TIME_HEADER_CHANGES
# Use it if some header files are being generated by the compilation process.
#
# ACCOUNT_FOR_PCH
# Use it if precompiled headers are enabled in your project. Automatically includes uses
# ACCOUNT_FOR_COMPILE_TIME_HEADER_CHANGES as well.
# See here for details: https://ccache.dev/manual/4.2.1.html#_precompiled_headers
#
# ACCOUNT_FOR_MODULES
# Use it for projects with C++20 modules. Requires DIRECT_DEPEND mode.
#
# PREFIXES
# A list of other tools that should be used together with ccache as a compiler launcher
# (i.e. distcc, icecc, sccache-dist, ...).
#
function(enable_ccache)
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
message(FATAL_ERROR "'enable_ccache' function should be called from the top-level CMakeLists.txt file!")
# otherwise, it will not work for XCode
endif()
set(_options QUIET REQUIRED ACCOUNT_FOR_COMPILE_TIME_HEADER_CHANGES ACCOUNT_FOR_PCH ACCOUNT_FOR_MODULES)
set(_one_value_args PROGRAM MODE BASE_DIR)
set(_multi_value_args PREFIXES)
cmake_parse_arguments(PARSE_ARGV 0 _enable_ccache "${_options}" "${_one_value_args}" "${_multi_value_args}")
# validate and process arguments
if(_enable_ccache_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Invalid arguments '${_enable_ccache_UNPARSED_ARGUMENTS}'")
endif()
if(_enable_ccache_KEYWORDS_MISSING_VALUES)
message(FATAL_ERROR "No value provided for '${_enable_ccache_KEYWORDS_MISSING_VALUES}'")
endif()
if(_enable_ccache_MODE)
set(_valid_mode_values DIRECT_PREPROCESSOR DIRECT_DEPEND PREPROCESSOR DEPEND)
if(NOT _enable_ccache_MODE IN_LIST _valid_mode_values)
message(FATAL_ERROR "'MODE' should be one of ${_valid_mode_values}")
endif()
endif()
if(NOT _enable_ccache_QUIET)
message(STATUS "Enabling ccache")
endif()
if(${_enable_ccache_REQUIRED})
set(_error_log_level FATAL_ERROR)
elseif(NOT _enable_ccache_QUIET)
set(_error_log_level STATUS)
endif()
if(NOT CMAKE_GENERATOR MATCHES "Ninja|Makefiles|Xcode")
if(DEFINED _error_log_level)
message(${_error_log_level} "ccache support not enabled: unsupported generator '${CMAKE_GENERATOR}'")
endif()
_enable_ccache_failed()
endif()
if(NOT DEFINED _enable_ccache_PROGRAM)
set(_enable_ccache_PROGRAM ccache)
endif()
find_program(CCACHE_PATH ${_enable_ccache_PROGRAM})
if(CCACHE_PATH)
if(NOT _enable_ccache_QUIET)
message(STATUS " Executable: ${CCACHE_PATH}")
endif()
# get version number
execute_process(COMMAND "${CCACHE_PATH}" --version OUTPUT_VARIABLE _output)
string(REPLACE "\n" ";" _output "${_output}")
foreach(_line ${_output})
string(REGEX REPLACE "ccache version ([\\.0-9]+)$" "\\1" _ccache_version "${_line}")
if(_ccache_version)
if(NOT _enable_ccache_QUIET)
message(STATUS " Version: ${_ccache_version}")
endif()
break()
endif()
endforeach()
else()
if(DEFINED _error_log_level)
message(${_error_log_level} " '${_enable_ccache_PROGRAM}' executable was not found")
endif()
_enable_ccache_failed()
endif()
if("${_ccache_version}" VERSION_LESS 3.3.0)
list(APPEND _ccacheEnv CCACHE_CPP2=1) # avoids spurious warnings with some compilers for ccache older than 3.3
endif()
if(_enable_ccache_MODE STREQUAL DIRECT_DEPEND)
list(APPEND _ccacheEnv CCACHE_DIRECT=1 CCACHE_DEPEND=1)
elseif(_enable_ccache_MODE STREQUAL PREPROCESSOR)
list(APPEND _ccacheEnv CCACHE_NO_DIRECT=1 CCACHE_NO_DEPEND=1)
elseif(_enable_ccache_MODE STREQUAL DEPEND)
list(APPEND _ccacheEnv CCACHE_NO_DIRECT=1 CCACHE_DEPEND=1)
else()
set(_enable_ccache_MODE DIRECT_PREPROCESSOR)
list(APPEND _ccacheEnv CCACHE_DIRECT=1 CCACHE_NO_DEPEND=1)
endif()
if(_enable_ccache_BASE_DIR)
# CCACHE_ABSSTDERR=1 # reverts absolute paths after applying CCACHE_BASEDIR
if(NOT EXISTS ${_enable_ccache_BASE_DIR})
message(FATAL_ERROR "Base directory '${_enable_ccache_BASE_DIR}' does not exist")
endif()
list(APPEND _ccacheEnv "CCACHE_BASEDIR=${_enable_ccache_BASE_DIR}")
endif()
if(_enable_ccache_PREFIXES)
string(REPLACE ";" " " _prefixes_txt "${_enable_ccache_PREFIXES}")
list(APPEND _ccacheEnv "CCACHE_PREFIX=${_prefixes_txt}")
endif()
if(_enable_ccache_ACCOUNT_FOR_COMPILE_TIME_HEADER_CHANGES)
list(APPEND _sloppiness include_file_mtime include_file_ctime)
endif()
if(_enable_ccache_ACCOUNT_FOR_PCH)
list(APPEND _sloppiness pch_defines time_macros include_file_mtime include_file_ctime)
endif()
if(_enable_ccache_ACCOUNT_FOR_MODULES)
if(NOT _enable_ccache_MODE STREQUAL DIRECT_DEPEND)
message(FATAL_ERROR "DIRECT_DEPEND mode required with ACCOUNT_FOR_MODULES option")
endif()
list(APPEND _sloppiness modules)
endif()
if(_sloppiness)
list(REMOVE_DUPLICATES _sloppiness)
string(REPLACE ";" "," _sloppiness_txt "${_sloppiness}")
list(APPEND _ccacheEnv "CCACHE_SLOPPINESS=${_sloppiness_txt}")
endif()
if(NOT _enable_ccache_QUIET)
message(STATUS " Environment: ${_ccacheEnv}")
endif()
if(CMAKE_GENERATOR MATCHES "Ninja|Makefiles")
foreach(_lang IN ITEMS C CXX OBJC OBJCXX CUDA)
set(CMAKE_${_lang}_COMPILER_LAUNCHER
${CMAKE_COMMAND} -E env
${_ccacheEnv} ${CCACHE_PATH}
PARENT_SCOPE
)
endforeach()
elseif(CMAKE_GENERATOR STREQUAL Xcode)
# Each of the Xcode project variables allow specifying only a single value, but the ccache command line needs to have multiple options.
# A separate launch script needs to be written out and the project variables pointed at them.
foreach(_lang IN ITEMS C CXX)
set(launch${_lang} ${CMAKE_BINARY_DIR}/launch-${_lang})
file(WRITE ${launch${_lang}} "#!/bin/bash\n\n")
foreach(keyVal IN LISTS _ccacheEnv)
file(APPEND ${launch${_lang}} "export ${keyVal}\n")
endforeach()
file(APPEND ${launch${_lang}}
"exec \"${CCACHE_PROGRAM}\" "
"\"${CMAKE_${_lang}_COMPILER}\" \"$@\"\n"
)
execute_process(COMMAND chmod a+rx ${launch${_lang}})
endforeach()
set(CMAKE_XCODE_ATTRIBUTE_CC ${launchC} PARENT_SCOPE)
set(CMAKE_XCODE_ATTRIBUTE_CXX ${launchCXX} PARENT_SCOPE)
set(CMAKE_XCODE_ATTRIBUTE_LD ${launchC} PARENT_SCOPE)
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS ${launchCXX} PARENT_SCOPE)
endif()
if(NOT _enable_ccache_QUIET)
message(STATUS "Enabling ccache - done")
endif()
endfunction()

View File

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

View File

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

View File

@@ -0,0 +1,31 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Mateusz Pusz
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.4)
function(ensure_entry_point)
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
message(FATAL_ERROR "'${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt' is meant to be used only "
"as a CMake entry point and should not be included from other CMake files. "
"Include '${CMAKE_CURRENT_SOURCE_DIR}/src/CMaskeLists.txt' directly instead.")
endif()
endfunction()

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 54 KiB

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -11,7 +11,7 @@ enough to be used with other Linear Algebra libraries existing on the market.
All of the examples provided in this chapter refer to the official proposal of the
Linear Algebra Library for the C++23 defined in `P1385 <https://wg21.link/P1385>`_
and its latest implementation from `GitHub <https://github.com/BobSteagall/wg21>`_
or `Conan <https://bintray.com/twonington/public-conan/linear_algebra%3Apublic-conan>`_.
or `Conan <https://twonington.jfrog.io/artifactory/api/conan/conan-oss>`_.
Also, to simplify the examples all of them assume::
using namespace std::math;

View File

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

View File

@@ -53,8 +53,8 @@ distance spherical_distance(position from, position to)
return distance(earth_radius * central_angle);
} else {
// the haversine formula
const auto sin_lat = sin(lat2 - lat1) / 2;
const auto sin_lon = sin(lon2 - lon1) / 2;
const auto sin_lat = sin((lat2 - lat1) / 2);
const auto sin_lon = sin((lon2 - lon1) / 2);
const auto central_angle = 2 * asin(sqrt(sin_lat * sin_lat + cos(lat1) * cos(lat2) * sin_lon * sin_lon));
return distance(earth_radius * central_angle);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,34 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/bits/basic_concepts.h>
namespace units {
template<Dimension D>
struct point_origin {
using dimension = D;
};
} // namespace units

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -22,11 +22,11 @@
#pragma once
#include <units/bits/deduced_symbol_text.h>
#include <units/bits/derived_symbol_text.h>
#include <units/bits/external/downcasting.h>
// IWYU pragma: begin_exports
#include <units/bits/deduced_unit.h>
#include <units/bits/derived_unit.h>
#include <units/bits/external/fixed_string.h>
#include <units/prefix.h>
#include <units/ratio.h>
@@ -155,37 +155,12 @@ struct prefixed_unit : downcast_dispatch<Child, scaled_unit<P::ratio * U::ratio,
template<typename Child, DerivedDimension Dim, Unit U, Unit... URest>
requires detail::same_scaled_units<typename Dim::recipe, U, URest...> &&
(U::is_named && (URest::is_named && ... && true))
struct deduced_unit : downcast_dispatch<Child, detail::deduced_unit<Dim, U, URest...>> {
struct derived_unit : downcast_dispatch<Child, detail::derived_unit<Dim, U, URest...>> {
static constexpr bool is_named = false;
static constexpr auto symbol = detail::deduced_symbol_text<Dim, U, URest...>();
static constexpr auto symbol = detail::derived_symbol_text<Dim, U, URest...>();
using prefix_family = no_prefix;
};
/**
* @brief A unit with a deduced ratio and symbol that can be used as a named unit for children
*
* Defines a new unit with a deduced ratio and symbol based on the recipe from the provided
* derived dimension. The number and order of provided units should match the recipe of the
* derived dimension. All of the units provided should also be a named ones so it is possible
* to create a deduced symbol text.
*
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
* @tparam Dim a derived dimension recipe to use for deduction
* @tparam U the unit of the first composite dimension from provided derived dimension's recipe
* @tparam URest the units for the rest of dimensions from the recipe
*/
template<typename Child, DerivedDimension Dim, Unit U, Unit... URest>
requires detail::same_scaled_units<typename Dim::recipe, U, URest...> &&
(U::is_named && (URest::is_named && ... && true))
// TODO - 'noble' is placeholder to sort of mean can pass its name on to other deduced units
struct noble_deduced_unit : downcast_dispatch<Child, detail::deduced_unit<Dim, U, URest...>> {
static constexpr bool is_named = true;
static constexpr auto symbol = detail::deduced_symbol_text<Dim, U, URest...>();
using prefix_family = no_prefix;
};
/**
* @brief A named unit with a deduced ratio
*
@@ -203,7 +178,7 @@ struct noble_deduced_unit : downcast_dispatch<Child, detail::deduced_unit<Dim, U
*/
template<typename Child, DerivedDimension Dim, basic_symbol_text Symbol, PrefixFamily PF, Unit U, Unit... URest>
requires detail::same_scaled_units<typename Dim::recipe, U, URest...>
struct named_deduced_unit : downcast_dispatch<Child, detail::deduced_unit<Dim, U, URest...>> {
struct named_derived_unit : downcast_dispatch<Child, detail::derived_unit<Dim, U, URest...>> {
static constexpr bool is_named = true;
static constexpr auto symbol = Symbol;
using prefix_family = PF;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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