mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-04 20:54:28 +02:00
Merge branch 'master' of https://github.com/mpusz/units
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
||||
[submodule "cmake/common"]
|
||||
path = cmake/common
|
||||
url = https://github.com/mpusz/cmake-scripts.git
|
@@ -27,7 +27,7 @@ project(mp-units)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
# include common tools and workarounds
|
||||
include(common/cmake/scripts)
|
||||
include(common/scripts)
|
||||
|
||||
# use Conan configuration if available
|
||||
conan_init(cmake)
|
||||
@@ -40,7 +40,7 @@ conan_init(cmake)
|
||||
add_subdirectory(src)
|
||||
|
||||
# set restrictive compilation warnings
|
||||
set_warnings(units)
|
||||
set_warnings(mp-units)
|
||||
|
||||
# add unit tests
|
||||
enable_testing()
|
||||
|
1
build.py
1
build.py
@@ -9,7 +9,6 @@ if __name__ == "__main__":
|
||||
|
||||
# dependencies
|
||||
remotes = [
|
||||
("https://api.bintray.com/conan/bincrafters/public-conan", True, "bincrafters"),
|
||||
("https://api.bintray.com/conan/twonington/public-conan", True, "linear-algebra")
|
||||
],
|
||||
build_policy = ["mp-units", "outdated"],
|
||||
|
Submodule cmake/common deleted from eb5fbd40d1
46
cmake/common/conan.cmake
Normal file
46
cmake/common/conan.cmake
Normal file
@@ -0,0 +1,46 @@
|
||||
# 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.
|
||||
|
||||
|
||||
# Helper to use conan generated configuration if provided
|
||||
macro(conan_init generator)
|
||||
if(${generator} STREQUAL "cmake_paths")
|
||||
include(${CMAKE_BINARY_DIR}/conan_paths.cmake OPTIONAL)
|
||||
elseif(${generator} STREQUAL "cmake")
|
||||
if(NOT DEFINED CONAN_PACKAGE_NAME)
|
||||
if(EXISTS ${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||
conan_basic_setup(TARGETS)
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown Conan generator: ${generator}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
|
||||
# Checks if conan installed testing dependencies
|
||||
macro(conan_check_testing test_framework)
|
||||
if(NOT TARGET CONAN_PKG::${test_framework})
|
||||
message(FATAL_ERROR "CONAN_PKG::${test_framework} not found!\nPlease run `conan install` with `-e CONAN_RUN_TESTS=True`.")
|
||||
endif()
|
||||
endmacro()
|
81
cmake/common/install.cmake
Normal file
81
cmake/common/install.cmake
Normal file
@@ -0,0 +1,81 @@
|
||||
# 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.
|
||||
|
||||
|
||||
# A path to scripts directory
|
||||
set(CMAKE_SCRIPTS_ROOT ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Install provided targets
|
||||
function(install_targets)
|
||||
if(NOT CMAKE_INSTALL_BINDIR)
|
||||
set(CMAKE_INSTALL_BINDIR "bin")
|
||||
endif()
|
||||
if(NOT CMAKE_INSTALL_LIBDIR)
|
||||
set(CMAKE_INSTALL_LIBDIR "lib")
|
||||
endif()
|
||||
if(NOT CMAKE_INSTALL_INCLUDEDIR)
|
||||
set(CMAKE_INSTALL_INCLUDEDIR "include")
|
||||
endif()
|
||||
install(TARGETS ${ARGN}
|
||||
EXPORT ${PROJECT_NAME}Targets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # TODO Remove when CMAKE 3.14
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # TODO Remove when CMAKE 3.14
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # TODO Remove when CMAKE 3.14
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
# Generate configuration files and install the package
|
||||
function(configure_and_install configure_in_file_path namespace version_compare_rules)
|
||||
if(NOT APPLE)
|
||||
set(CMAKE_INSTALL_RPATH ${ORIGIN})
|
||||
endif()
|
||||
|
||||
# prepare installation files
|
||||
include(CMakePackageConfigHelpers)
|
||||
set(ConfigPackageSource ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME})
|
||||
set(ConfigPackageDestination lib/cmake/${PROJECT_NAME})
|
||||
write_basic_package_version_file(
|
||||
${ConfigPackageSource}/${PROJECT_NAME}-config-version.cmake
|
||||
COMPATIBILITY ${version_compare_rules})
|
||||
configure_package_config_file(${configure_in_file_path}
|
||||
${ConfigPackageSource}/${PROJECT_NAME}-config.cmake
|
||||
INSTALL_DESTINATION ${ConfigPackageDestination})
|
||||
|
||||
# install library
|
||||
install(EXPORT ${PROJECT_NAME}Targets
|
||||
DESTINATION ${ConfigPackageDestination}
|
||||
FILE ${PROJECT_NAME}-targets.cmake
|
||||
NAMESPACE ${namespace}::
|
||||
COMPONENT Devel)
|
||||
install(FILES
|
||||
"${ConfigPackageSource}/${PROJECT_NAME}-config.cmake"
|
||||
"${ConfigPackageSource}/${PROJECT_NAME}-config-version.cmake"
|
||||
DESTINATION ${ConfigPackageDestination}
|
||||
COMPONENT Devel)
|
||||
|
||||
# local package
|
||||
export(EXPORT ${PROJECT_NAME}Targets
|
||||
NAMESPACE ${namespace}::
|
||||
FILE ${ConfigPackageSource}/${PROJECT_NAME}-targets.cmake)
|
||||
endfunction()
|
28
cmake/common/scripts.cmake
Normal file
28
cmake/common/scripts.cmake
Normal file
@@ -0,0 +1,28 @@
|
||||
# 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.
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
include(conan)
|
||||
include(install)
|
||||
include(static_analysis)
|
||||
include(warnings)
|
1
cmake/common/simple-config.cmake.in
Normal file
1
cmake/common/simple-config.cmake.in
Normal file
@@ -0,0 +1 @@
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake")
|
44
cmake/common/static_analysis.cmake
Normal file
44
cmake/common/static_analysis.cmake
Normal file
@@ -0,0 +1,44 @@
|
||||
# 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.
|
||||
|
||||
|
||||
macro(enable_clang_tidy)
|
||||
find_program(clang_tidy_cmd NAMES "clang-tidy")
|
||||
if(NOT clang_tidy_cmd)
|
||||
message(WARNING "clang-tidy not found!")
|
||||
else()
|
||||
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/.clang-tidy")
|
||||
message(FATAL_ERROR "'${CMAKE_SOURCE_DIR}/.clang-tidy' configuration file not found!")
|
||||
endif()
|
||||
set(CMAKE_CXX_CLANG_TIDY "${clang_tidy_cmd}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
|
||||
macro(enable_iwyu)
|
||||
find_program(iwyu_cmd NAMES "include-what-you-use")
|
||||
if(NOT iwyu_cmd)
|
||||
message(WARNING "include-what-you-use not found!")
|
||||
else()
|
||||
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "${iwyu_cmd}")
|
||||
endif()
|
||||
endmacro()
|
110
cmake/common/warnings.cmake
Normal file
110
cmake/common/warnings.cmake
Normal file
@@ -0,0 +1,110 @@
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2016 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.
|
||||
|
||||
# Based on https://github.com/lefticus/cpp_starter_project/blob/master/cmake/CompilerWarnings.cmake
|
||||
|
||||
# Configure compiler warning level
|
||||
function(set_warnings target)
|
||||
option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" TRUE)
|
||||
|
||||
if(NOT TARGET ${target})
|
||||
message(FATAL_ERROR "'${target}' is not a CMake target")
|
||||
endif()
|
||||
|
||||
set(MSVC_WARNINGS
|
||||
/W4 # Baseline reasonable warnings
|
||||
/w14062 # enumerator 'identifier' in a switch of enum 'enumeration' is not handled
|
||||
/w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data
|
||||
/w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
|
||||
/w14263 # 'function': member function does not override any base class virtual member function
|
||||
/w14265 # 'classname': class has virtual functions, but destructor is not
|
||||
# virtual instances of this class may not be destructed correctly
|
||||
/w14266 # 'function': no override available for virtual member function from base 'type'; function is hidden
|
||||
/w14287 # 'operator': unsigned/negative constant mismatch
|
||||
/we4289 # nonstandard extension used: 'variable': loop control variable
|
||||
# declared in the for-loop is used outside the for-loop scope
|
||||
/w14296 # 'operator': expression is always 'boolean_value'
|
||||
/w14311 # 'variable': pointer truncation from 'type1' to 'type2'
|
||||
/w14545 # expression before comma evaluates to a function which is missing
|
||||
# an argument list
|
||||
/w14546 # function call before comma missing argument list
|
||||
/w14547 # 'operator': operator before comma has no effect; expected
|
||||
# operator with side-effect
|
||||
/w14549 # 'operator': operator before comma has no effect; did you intend
|
||||
# 'operator'?
|
||||
/w14555 # expression has no effect; expected expression with side- effect
|
||||
/w14619 # pragma warning: there is no warning number 'number'
|
||||
/w14640 # Enable warning on thread un-safe static member initialization
|
||||
/w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may
|
||||
# cause unexpected runtime behavior.
|
||||
/w14905 # wide string literal cast to 'LPSTR'
|
||||
/w14906 # string literal cast to 'LPWSTR'
|
||||
/w14928 # illegal copy-initialization; more than one user-defined
|
||||
# conversion has been implicitly applied
|
||||
/permissive- # standards conformance mode for MSVC compiler.
|
||||
)
|
||||
|
||||
set(CLANG_WARNINGS
|
||||
-Wall
|
||||
-Wextra # reasonable and standard
|
||||
-Wpedantic # warn if non-standard C++ is used
|
||||
-Wshadow # warn the user if a variable declaration shadows one from a parent context
|
||||
-Wnon-virtual-dtor # warn the user if a class with virtual functions has a
|
||||
# non-virtual destructor. This helps catch hard to
|
||||
# track down memory errors
|
||||
-Wold-style-cast # warn for c-style casts
|
||||
-Wcast-align # warn for potential performance problem casts
|
||||
-Wunused # warn on anything being unused
|
||||
-Woverloaded-virtual # warn if you overload (not override) a virtual function
|
||||
-Wcast-qual # warn on dropping const or volatile qualifiers
|
||||
-Wconversion # warn on type conversions that may lose data
|
||||
-Wsign-conversion # warn on sign conversions
|
||||
-Wnull-dereference # warn if a null dereference is detected
|
||||
-Wdouble-promotion # warn if float is implicit promoted to double
|
||||
-Wformat=2 # warn on security issues around functions that format output (ie printf)
|
||||
)
|
||||
|
||||
if(WARNINGS_AS_ERRORS)
|
||||
set(CLANG_WARNINGS ${CLANG_WARNINGS} -Werror)
|
||||
set(MSVC_WARNINGS ${MSVC_WARNINGS} /WX)
|
||||
endif()
|
||||
|
||||
set(GCC_WARNINGS
|
||||
${CLANG_WARNINGS}
|
||||
-Wmisleading-indentation # warn if indentation implies blocks where blocks do not exist
|
||||
-Wduplicated-cond # warn if if / else chain has duplicated conditions
|
||||
-Wduplicated-branches # warn if if / else branches have duplicated code
|
||||
-Wlogical-op # warn about logical operations being used where bitwise were probably wanted
|
||||
)
|
||||
|
||||
if(MSVC)
|
||||
string(REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE)
|
||||
target_compile_options(${target} INTERFACE ${MSVC_WARNINGS})
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
|
||||
target_compile_options(${target} INTERFACE ${CLANG_WARNINGS})
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
target_compile_options(${target} INTERFACE ${GCC_WARNINGS})
|
||||
else()
|
||||
message(AUTHOR_WARNING "No compiler warnings set for '${CMAKE_CXX_COMPILER_ID}' compiler.")
|
||||
endif()
|
||||
endfunction()
|
65
conanfile.py
65
conanfile.py
@@ -21,7 +21,7 @@
|
||||
# SOFTWARE.
|
||||
|
||||
from conans import ConanFile, CMake, tools
|
||||
from conans.tools import Version
|
||||
from conans.tools import Version, check_min_cppstd
|
||||
from conans.errors import ConanInvalidConfiguration
|
||||
import re
|
||||
|
||||
@@ -38,17 +38,18 @@ def get_version():
|
||||
class UnitsConan(ConanFile):
|
||||
name = "mp-units"
|
||||
version = get_version()
|
||||
author = "Mateusz Pusz"
|
||||
license = "https://github.com/mpusz/units/blob/master/LICENSE.md"
|
||||
url = "https://github.com/mpusz/units"
|
||||
homepage = "https://github.com/mpusz/units"
|
||||
description = "Physical Units library for C++"
|
||||
exports = ["LICENSE.md"]
|
||||
exports_sources = ["docs/*", "src/*", "test/*", "cmake/*", "example/*","CMakeLists.txt"]
|
||||
topics = ("units", "dimensions", "quantities", "dimensional-analysis", "physical-quantities", "physical-units", "system-of-units", "cpp23", "cpp20", "library", "quantity-manipulation")
|
||||
license = "MIT"
|
||||
url = "https://github.com/mpusz/units"
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
requires = (
|
||||
"fmt/7.0.3",
|
||||
"ms-gsl/3.1.0"
|
||||
)
|
||||
exports = ["LICENSE.md"]
|
||||
exports_sources = ["docs/*", "src/*", "test/*", "cmake/*", "example/*","CMakeLists.txt"]
|
||||
# scm = {
|
||||
# "type": "git",
|
||||
# "url": "auto",
|
||||
@@ -61,6 +62,19 @@ class UnitsConan(ConanFile):
|
||||
def _run_tests(self):
|
||||
return tools.get_env("CONAN_RUN_TESTS", False)
|
||||
|
||||
def _validate_compiler_settings(self):
|
||||
compiler = self.settings.compiler
|
||||
version = Version(self.settings.compiler.version)
|
||||
if compiler == "gcc":
|
||||
if version < "9.3":
|
||||
raise ConanInvalidConfiguration("mp-units requires at least g++-9.3")
|
||||
elif compiler == "Visual Studio":
|
||||
if version < "16":
|
||||
raise ConanInvalidConfiguration("mp-units requires at least MSVC 16")
|
||||
else:
|
||||
raise ConanInvalidConfiguration("mp-units is supported only by gcc and Visual Studio so far")
|
||||
check_min_cppstd(self, "20")
|
||||
|
||||
def _configure_cmake(self, folder="src"):
|
||||
cmake = CMake(self)
|
||||
if self._run_tests:
|
||||
@@ -72,15 +86,7 @@ class UnitsConan(ConanFile):
|
||||
return cmake
|
||||
|
||||
def configure(self):
|
||||
if self.settings.compiler != "gcc" and self.settings.compiler != "Visual Studio": # and self.settings.compiler != "clang":
|
||||
raise ConanInvalidConfiguration("Library works only with gcc and Visual Studio so far") # and clang")
|
||||
if self.settings.compiler == "gcc" and Version(self.settings.compiler.version) < "9":
|
||||
raise ConanInvalidConfiguration("Library requires at least g++-9")
|
||||
if self.settings.compiler == "Visual Studio" and Version(self.settings.compiler.version) < "16":
|
||||
raise ConanInvalidConfiguration("Library requires at least Visual Studio 2019")
|
||||
if self.settings.compiler == "clang" and Version(self.settings.compiler.version) < "11":
|
||||
raise ConanInvalidConfiguration("Library requires at least clang++-11")
|
||||
tools.check_min_cppstd(self, "20")
|
||||
self._validate_compiler_settings()
|
||||
|
||||
def requirements(self):
|
||||
if ((self.settings.compiler == "gcc" and Version(self.settings.compiler.version) < "10") or
|
||||
@@ -104,18 +110,25 @@ class UnitsConan(ConanFile):
|
||||
cmake = self._configure_cmake()
|
||||
cmake.install()
|
||||
|
||||
def package_info(self):
|
||||
if self.settings.compiler == "gcc":
|
||||
self.cpp_info.cxxflags = [
|
||||
"-Wno-literal-suffix",
|
||||
"-Wno-non-template-friend",
|
||||
]
|
||||
if Version(self.settings.compiler.version) < "10":
|
||||
self.cpp_info.cxxflags.extend([
|
||||
"-fconcepts"
|
||||
])
|
||||
|
||||
def package_id(self):
|
||||
self.info.settings.clear()
|
||||
self.info.settings.compiler = self.settings.compiler
|
||||
self.info.settings.compiler.version = self.settings.compiler.version
|
||||
|
||||
def package_info(self):
|
||||
compiler = self.settings.compiler
|
||||
version = Version(self.settings.compiler.version)
|
||||
if compiler == "gcc":
|
||||
self.cpp_info.cxxflags = [
|
||||
"-Wno-literal-suffix",
|
||||
"-Wno-non-template-friend",
|
||||
]
|
||||
if version < "10":
|
||||
self.cpp_info.cxxflags.extend([
|
||||
"-fconcepts"
|
||||
])
|
||||
elif compiler == "Visual Studio":
|
||||
self.cpp_info.cxxflags = [
|
||||
"/utf-8",
|
||||
"/wd4455"
|
||||
]
|
||||
|
@@ -8,6 +8,7 @@
|
||||
- catch2 updated to 2.13.0
|
||||
- doxygen updated to 1.8.18
|
||||
- ms-gsl 3.1.0 dependency added
|
||||
- MSVC 16.7 support added
|
||||
- Added angle as SI base dimension (thanks [@kwikius](https://github.com/kwikius))
|
||||
- Added STL random number distribution wrappers (thanks [@yasamoka](https://github.com/yasamoka))
|
||||
- `math.h` function signatures refactored to use a `Quantity` concept (thanks [@kwikius](https://github.com/kwikius))
|
||||
|
@@ -20,6 +20,8 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
option(GENERATE_DOCS "Generate project documenation" ON)
|
||||
if(NOT GENERATE_DOCS)
|
||||
return()
|
||||
|
@@ -80,7 +80,7 @@ in *~/.conan/profile* directory. An example profile can look as follows:
|
||||
arch=x86_64
|
||||
arch_build=x86_64
|
||||
compiler=gcc
|
||||
compiler.version=9
|
||||
compiler.version=10
|
||||
compiler.cppstd=20
|
||||
compiler.libcxx=libstdc++11
|
||||
build_type=Release
|
||||
@@ -89,8 +89,8 @@ in *~/.conan/profile* directory. An example profile can look as follows:
|
||||
[build_requires]
|
||||
|
||||
[env]
|
||||
CC=/usr/bin/gcc-9
|
||||
CXX=/usr/bin/g++-9
|
||||
CC=/usr/bin/gcc-10
|
||||
CXX=/usr/bin/g++-10
|
||||
|
||||
.. tip::
|
||||
|
||||
|
@@ -20,9 +20,11 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
function(add_example target)
|
||||
add_executable(${target} ${target}.cpp)
|
||||
target_link_libraries(${target} PRIVATE mp::units)
|
||||
target_link_libraries(${target} PRIVATE mp-units::mp-units)
|
||||
endfunction()
|
||||
|
||||
add_example(box_example)
|
||||
|
@@ -20,9 +20,11 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
function(add_example target)
|
||||
add_executable(${target}_alt ${target}.cpp)
|
||||
target_link_libraries(${target}_alt PRIVATE mp::units)
|
||||
target_link_libraries(${target}_alt PRIVATE mp-units::mp-units)
|
||||
endfunction()
|
||||
|
||||
add_example(box_example)
|
||||
|
@@ -31,14 +31,14 @@ project(mp-units
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../cmake")
|
||||
|
||||
# include common tools and workarounds
|
||||
include(common/cmake/scripts)
|
||||
include(common/scripts)
|
||||
|
||||
# use Conan configuration if available
|
||||
conan_init(cmake)
|
||||
|
||||
# library definition
|
||||
add_library(units INTERFACE)
|
||||
#target_sources(units INTERFACE
|
||||
add_library(mp-units INTERFACE)
|
||||
#target_sources(mp-units INTERFACE
|
||||
# include/units/dimension.h
|
||||
# include/units/quantity.h
|
||||
# include/units/unit.h
|
||||
@@ -52,55 +52,55 @@ add_library(units INTERFACE)
|
||||
# include/units/si/time.h
|
||||
# include/units/si/speed.h
|
||||
#)
|
||||
target_compile_features(units INTERFACE cxx_std_20)
|
||||
target_link_libraries(units
|
||||
target_compile_features(mp-units INTERFACE cxx_std_20)
|
||||
target_link_libraries(mp-units
|
||||
INTERFACE
|
||||
$<IF:$<TARGET_EXISTS:CONAN_PKG::fmt>,CONAN_PKG::fmt,fmt::fmt>
|
||||
$<IF:$<TARGET_EXISTS:CONAN_PKG::ms-gsl>,CONAN_PKG::ms-gsl,Microsoft.GSL::GSL>
|
||||
)
|
||||
target_include_directories(units
|
||||
target_include_directories(mp-units
|
||||
INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
target_link_libraries(units
|
||||
target_link_libraries(mp-units
|
||||
INTERFACE
|
||||
$<IF:$<TARGET_EXISTS:CONAN_PKG::range-v3>,CONAN_PKG::range-v3,range-v3::range-v3>
|
||||
)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
target_compile_options(units
|
||||
target_compile_options(mp-units
|
||||
INTERFACE
|
||||
-Wno-literal-suffix
|
||||
-Wno-non-template-friend
|
||||
)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0)
|
||||
target_compile_options(units
|
||||
target_compile_options(mp-units
|
||||
INTERFACE
|
||||
-fconcepts
|
||||
)
|
||||
target_link_libraries(units
|
||||
target_link_libraries(mp-units
|
||||
INTERFACE
|
||||
$<IF:$<TARGET_EXISTS:CONAN_PKG::range-v3>,CONAN_PKG::range-v3,range-v3::range-v3>
|
||||
)
|
||||
endif()
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
target_compile_options(units
|
||||
target_compile_options(mp-units
|
||||
INTERFACE
|
||||
/utf-8 # Specifies both the source character set and the execution character set as UTF-8
|
||||
/wd4455 # 'operator name': literal suffix identifiers that do not start with an underscore are reserved
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(mp::units ALIAS units)
|
||||
add_library(mp-units::mp-units ALIAS mp-units)
|
||||
|
||||
# installation info
|
||||
install_targets(units)
|
||||
install_targets(mp-units)
|
||||
install(DIRECTORY include/units
|
||||
DESTINATION include
|
||||
COMPONENT Devel
|
||||
)
|
||||
|
||||
# generate configuration files and install the package
|
||||
configure_and_install(../cmake/common/cmake/simple-config.cmake.in mp SameMajorVersion)
|
||||
configure_and_install(../cmake/common/simple-config.cmake.in mp-units SameMajorVersion)
|
||||
|
61
src/include/units/bits/pow.h
Normal file
61
src/include/units/bits/pow.h
Normal file
@@ -0,0 +1,61 @@
|
||||
// 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 <cstdint>
|
||||
#include <cassert>
|
||||
|
||||
namespace units::detail {
|
||||
|
||||
constexpr std::intmax_t ipow10(std::intmax_t exp)
|
||||
{
|
||||
assert(exp >= 0);
|
||||
if (exp == 0) return 1;
|
||||
std::intmax_t result = 1;
|
||||
while (exp > 0) {
|
||||
result *= 10;
|
||||
--exp;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Rep>
|
||||
constexpr Rep fpow10(std::intmax_t exp)
|
||||
{
|
||||
if (exp == 0) return Rep(1.0);
|
||||
Rep result = Rep(1.0);
|
||||
if (exp < 0) {
|
||||
while (exp < 0) {
|
||||
result = result / Rep(10.0);
|
||||
++exp;
|
||||
}
|
||||
} else {
|
||||
while (exp > 0) {
|
||||
result = result * Rep(10.0);
|
||||
--exp;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace units::detail
|
@@ -23,6 +23,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <units/bits/external/downcasting.h>
|
||||
#include <units/concepts.h>
|
||||
#include <units/ratio.h>
|
||||
#include <units/symbol_text.h>
|
||||
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <units/bits/common_quantity.h>
|
||||
#include <units/bits/dimension_op.h>
|
||||
#include <units/bits/pow.h>
|
||||
#include <units/bits/to_string.h>
|
||||
#include <units/quantity_cast.h>
|
||||
|
||||
@@ -342,9 +343,9 @@ template<typename D1, typename U1, typename Rep1, typename D2, typename U2, type
|
||||
using common_rep = decltype(lhs.count() * rhs.count());
|
||||
const ratio r = U1::ratio * U2::ratio;
|
||||
if constexpr (treat_as_floating_point<common_rep>) {
|
||||
return lhs.count() * rhs.count() * static_cast<common_rep>(r.num * fpow10<common_rep>(r.exp)) / static_cast<common_rep>(r.den);
|
||||
return lhs.count() * rhs.count() * static_cast<common_rep>(r.num * detail::fpow10<common_rep>(r.exp)) / static_cast<common_rep>(r.den);
|
||||
} else {
|
||||
return lhs.count() * rhs.count() * static_cast<common_rep>(r.num * ipow10(r.exp)) / static_cast<common_rep>(r.den);
|
||||
return lhs.count() * rhs.count() * static_cast<common_rep>(r.num * detail::ipow10(r.exp)) / static_cast<common_rep>(r.den);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -26,6 +26,9 @@
|
||||
#include <units/customization_points.h>
|
||||
#include <units/bits/dimension_op.h>
|
||||
#include <units/bits/external/type_traits.h>
|
||||
#include <units/bits/pow.h>
|
||||
#include <units/quantity.h>
|
||||
#include <units/quantity_point.h>
|
||||
#include <cassert>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@@ -35,38 +38,6 @@
|
||||
|
||||
namespace units {
|
||||
|
||||
constexpr std::intmax_t ipow10(std::intmax_t exp)
|
||||
{
|
||||
assert(exp >= 0);
|
||||
if (exp == 0) return 1;
|
||||
std::intmax_t result = 1;
|
||||
while (exp > 0) {
|
||||
result *= 10;
|
||||
--exp;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Rep>
|
||||
constexpr Rep fpow10(std::intmax_t exp)
|
||||
{
|
||||
if (exp == 0) return Rep(1.0);
|
||||
Rep result = Rep(1.0);
|
||||
if (exp < 0) {
|
||||
while (exp < 0) {
|
||||
result = result / Rep(10.0);
|
||||
++exp;
|
||||
}
|
||||
} else {
|
||||
while (exp > 0) {
|
||||
result = result * Rep(10.0);
|
||||
--exp;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// QuantityOf
|
||||
template<typename T, typename Dim>
|
||||
concept QuantityOf = Quantity<T> && Dimension<Dim> && equivalent_dim<typename T::dimension, Dim>;
|
||||
@@ -92,13 +63,13 @@ struct quantity_cast_impl<To, CRatio, CRep, true, true, false> {
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
if constexpr (treat_as_floating_point<CRep>) {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(fpow10<CRep>(CRatio.exp))));
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(detail::fpow10<CRep>(CRatio.exp))));
|
||||
} else {
|
||||
if constexpr (CRatio.exp > 0) {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(ipow10(CRatio.exp))));
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(detail::ipow10(CRatio.exp))));
|
||||
}
|
||||
else {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) / static_cast<CRep>(ipow10(-CRatio.exp))));
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) / static_cast<CRep>(detail::ipow10(-CRatio.exp))));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,21 +93,21 @@ struct quantity_cast_impl<To, CRatio, CRep, false, false, false> {
|
||||
{
|
||||
if constexpr (treat_as_floating_point<CRep>) {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) *
|
||||
static_cast<CRep>(fpow10<CRep>(CRatio.exp)) *
|
||||
static_cast<CRep>(detail::fpow10<CRep>(CRatio.exp)) *
|
||||
(static_cast<CRep>(CRatio.num) /
|
||||
static_cast<CRep>(CRatio.den))));
|
||||
} else {
|
||||
if constexpr (CRatio.exp > 0) {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) *
|
||||
static_cast<CRep>(CRatio.num) *
|
||||
static_cast<CRep>(ipow10(CRatio.exp)) /
|
||||
static_cast<CRep>(detail::ipow10(CRatio.exp)) /
|
||||
static_cast<CRep>(CRatio.den)));
|
||||
}
|
||||
else {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) *
|
||||
static_cast<CRep>(CRatio.num) /
|
||||
(static_cast<CRep>(CRatio.den) *
|
||||
static_cast<CRep>(ipow10(-CRatio.exp)))));
|
||||
static_cast<CRep>(detail::ipow10(-CRatio.exp)))));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -157,13 +128,13 @@ struct quantity_cast_impl<To, CRatio, CRep, true, false, false> {
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
if constexpr (treat_as_floating_point<CRep>) {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(fpow10<CRep>(CRatio.exp)) * (CRep{1} / static_cast<CRep>(CRatio.den))));
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(detail::fpow10<CRep>(CRatio.exp)) * (CRep{1} / static_cast<CRep>(CRatio.den))));
|
||||
} else {
|
||||
if constexpr (CRatio.exp > 0) {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(ipow10(CRatio.exp)) / static_cast<CRep>(CRatio.den)));
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(detail::ipow10(CRatio.exp)) / static_cast<CRep>(CRatio.den)));
|
||||
}
|
||||
else {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) / (static_cast<CRep>(ipow10(-CRatio.exp)) * static_cast<CRep>(CRatio.den))));
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) / (static_cast<CRep>(detail::ipow10(-CRatio.exp)) * static_cast<CRep>(CRatio.den))));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -184,13 +155,13 @@ struct quantity_cast_impl<To, CRatio, CRep, false, true, false> {
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
if constexpr (treat_as_floating_point<CRep>) {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio.num) * static_cast<CRep>(fpow10<CRep>(CRatio.exp))));
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio.num) * static_cast<CRep>(detail::fpow10<CRep>(CRatio.exp))));
|
||||
} else {
|
||||
if constexpr (CRatio.exp > 0) {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio.num) * static_cast<CRep>(ipow10(CRatio.exp))));
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio.num) * static_cast<CRep>(detail::ipow10(CRatio.exp))));
|
||||
}
|
||||
else {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio.num) / static_cast<CRep>(ipow10(-CRatio.exp))));
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio.num) / static_cast<CRep>(detail::ipow10(-CRatio.exp))));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,13 +173,13 @@ struct quantity_cast_impl<To, CRatio, CRep, true, true, false> {
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
if constexpr (treat_as_floating_point<CRep>) {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * fpow10<CRep>(CRatio.exp)));
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * detail::fpow10<CRep>(CRatio.exp)));
|
||||
} else {
|
||||
if constexpr (CRatio.exp > 0) {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * ipow10(CRatio.exp)));
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * detail::ipow10(CRatio.exp)));
|
||||
}
|
||||
else {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() / ipow10(-CRatio.exp)));
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() / detail::ipow10(-CRatio.exp)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -229,13 +200,13 @@ struct quantity_cast_impl<To, CRatio, CRep, false, false, false> {
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
if constexpr (treat_as_floating_point<CRep>) {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * fpow10<CRep>(CRatio.exp) * (CRatio.num / CRatio.den)));
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * detail::fpow10<CRep>(CRatio.exp) * (CRatio.num / CRatio.den)));
|
||||
} else {
|
||||
if constexpr (CRatio.exp > 0) {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * CRatio.num * ipow10(CRatio.exp) / CRatio.den));
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * CRatio.num * detail::ipow10(CRatio.exp) / CRatio.den));
|
||||
}
|
||||
else {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count()) * CRatio.num / (CRatio.den * ipow10(-CRatio.exp)));
|
||||
return To(static_cast<TYPENAME To::rep>(q.count()) * CRatio.num / (CRatio.den * detail::ipow10(-CRatio.exp)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -256,13 +227,13 @@ struct quantity_cast_impl<To, CRatio, CRep, true, false, false> {
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
if constexpr (treat_as_floating_point<CRep>) {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * fpow10<CRep>(CRatio.exp) / CRatio.den));
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * detail::fpow10<CRep>(CRatio.exp) / CRatio.den));
|
||||
} else {
|
||||
if constexpr (CRatio.exp > 0) {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * ipow10(CRatio.exp) / CRatio.den));
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * detail::ipow10(CRatio.exp) / CRatio.den));
|
||||
}
|
||||
else {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() / (ipow10(-CRatio.exp) * CRatio.den)));
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() / (detail::ipow10(-CRatio.exp) * CRatio.den)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -283,13 +254,13 @@ struct quantity_cast_impl<To, CRatio, CRep, false, true, false> {
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
if constexpr (treat_as_floating_point<CRep>) {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * CRatio.num * fpow10<CRep>(CRatio.exp)));
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * CRatio.num * detail::fpow10<CRep>(CRatio.exp)));
|
||||
} else {
|
||||
if constexpr (CRatio.exp > 0) {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * CRatio.num * ipow10(CRatio.exp)));
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * CRatio.num * detail::ipow10(CRatio.exp)));
|
||||
}
|
||||
else {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * CRatio.num / ipow10(-CRatio.exp)));
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * CRatio.num / detail::ipow10(-CRatio.exp)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#include <type_traits>
|
||||
#include <tuple>
|
||||
#include <algorithm>
|
||||
#include <gsl/gsl_assert>
|
||||
|
||||
namespace units {
|
||||
|
||||
@@ -50,6 +51,7 @@ struct ratio {
|
||||
|
||||
explicit constexpr ratio(std::intmax_t n, std::intmax_t d = 1, std::intmax_t e = 0): num(n), den(d), exp(e)
|
||||
{
|
||||
Expects(den != 0);
|
||||
detail::normalize(num, den, exp);
|
||||
}
|
||||
|
||||
|
@@ -20,6 +20,8 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
add_subdirectory(unit_test/runtime)
|
||||
add_subdirectory(unit_test/static)
|
||||
#add_subdirectory(metabench)
|
||||
|
@@ -20,6 +20,7 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
function(add_metabench_test target name erb_path range)
|
||||
metabench_add_dataset(${target} "${erb_path}" "${range}" NAME "${name}")
|
||||
|
@@ -20,6 +20,7 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
add_metabench_test(metabench.data.list.type_list.concepts_all "all concepts" type_list_concepts_all.cpp.erb "[3, 6, 9, 12, 15]")
|
||||
add_metabench_test(metabench.data.list.type_list.concepts_iface "concepts in interface" type_list_concepts_iface.cpp.erb "[3, 6, 9, 12, 15]")
|
||||
|
@@ -182,4 +182,4 @@ namespace units {
|
||||
template<TypeList List, template<typename, typename> typename Pred>
|
||||
using type_list_sort_t = type_list_sort<List, Pred>::type;
|
||||
|
||||
} // namespace units
|
||||
} // namespace units
|
||||
|
@@ -20,6 +20,7 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
add_metabench_test(metabench.data.make_dimension.no_concepts "no concepts" no_concepts.cpp.erb "[1, 2, 3, 4, 6, 8, 10]")
|
||||
add_metabench_test(metabench.data.make_dimension.concepts_iface "concepts iface" concepts_iface.cpp.erb "[1, 2, 3, 4, 6, 8, 10]")
|
||||
|
@@ -20,6 +20,7 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
add_metabench_test(metabench.data.ratio.create.std_ratio "std::ratio" create_std_ratio.cpp.erb "[1000, 2500, 5000, 7500, 10000]")
|
||||
add_metabench_test(metabench.data.ratio.create.ratio_type_constexpr "ratio with constexpr" create_ratio_type_constexpr.cpp.erb "[1000, 2500, 5000, 7500, 10000]")
|
||||
|
@@ -20,6 +20,8 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
# check if conan installed a test framework
|
||||
conan_check_testing(catch2)
|
||||
|
||||
@@ -33,7 +35,7 @@ add_executable(unit_tests_runtime
|
||||
)
|
||||
target_link_libraries(unit_tests_runtime
|
||||
PRIVATE
|
||||
mp::units
|
||||
mp-units::mp-units
|
||||
$<IF:$<TARGET_EXISTS:CONAN_PKG::catch2>,CONAN_PKG::catch2,Catch2::Catch2>
|
||||
)
|
||||
|
||||
|
@@ -606,4 +606,4 @@ TEST_CASE("piecewise_linear_distribution")
|
||||
CHECK(units_dist.intervals() == intervals_qty_vec);
|
||||
CHECK(units_dist.densities() == stl_dist.densities());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -938,7 +938,11 @@ TEST_CASE("precision specification", "[text][fmt]")
|
||||
CHECK(fmt::format("{:%.0Q %q}", 1.2345q_m) == "1 m");
|
||||
CHECK(fmt::format("{:%.1Q %q}", 1.2345q_m) == "1.2 m");
|
||||
CHECK(fmt::format("{:%.2Q %q}", 1.2345q_m) == "1.23 m");
|
||||
#ifdef COMP_MSVC
|
||||
CHECK(fmt::format("{:%.3Q %q}", 1.2345q_m) == "1.234 m");
|
||||
#else
|
||||
CHECK(fmt::format("{:%.3Q %q}", 1.2345q_m) == "1.235 m");
|
||||
#endif
|
||||
CHECK(fmt::format("{:%.4Q %q}", 1.2345q_m) == "1.2345 m");
|
||||
CHECK(fmt::format("{:%.5Q %q}", 1.2345q_m) == "1.23450 m");
|
||||
CHECK(fmt::format("{:%.10Q %q}", 1.2345q_m) == "1.2345000000 m");
|
||||
@@ -949,7 +953,11 @@ TEST_CASE("precision specification", "[text][fmt]")
|
||||
CHECK(fmt::format("{:%.0Q}", 1.2345q_m) == "1");
|
||||
CHECK(fmt::format("{:%.1Q}", 1.2345q_m) == "1.2");
|
||||
CHECK(fmt::format("{:%.2Q}", 1.2345q_m) == "1.23");
|
||||
#ifdef COMP_MSVC
|
||||
CHECK(fmt::format("{:%.3Q}", 1.2345q_m) == "1.234");
|
||||
#else
|
||||
CHECK(fmt::format("{:%.3Q}", 1.2345q_m) == "1.235");
|
||||
#endif
|
||||
CHECK(fmt::format("{:%.4Q}", 1.2345q_m) == "1.2345");
|
||||
CHECK(fmt::format("{:%.5Q}", 1.2345q_m) == "1.23450");
|
||||
CHECK(fmt::format("{:%.10Q}", 1.2345q_m) == "1.2345000000");
|
||||
@@ -980,10 +988,17 @@ TEST_CASE("type specification", "[text][fmt]")
|
||||
CHECK(fmt::format("{:%xQ %q}", 42q_m) == "2a m");
|
||||
CHECK(fmt::format("{:%XQ %q}", 42q_m) == "2A m");
|
||||
|
||||
#ifdef COMP_MSVC
|
||||
CHECK(fmt::format("{:%aQ %q}", 1.2345678q_m) == "0x1.3c0ca2a5b1d5dp+0 m");
|
||||
CHECK(fmt::format("{:%.3aQ %q}", 1.2345678q_m) == "0x1.3c1p+0 m");
|
||||
CHECK(fmt::format("{:%AQ %q}", 1.2345678q_m) == "0X1.3C0CA2A5B1D5DP+0 m");
|
||||
CHECK(fmt::format("{:%.3AQ %q}", 1.2345678q_m) == "0X1.3C1P+0 m");
|
||||
#else
|
||||
CHECK(fmt::format("{:%aQ %q}", 1.2345678q_m) == "0x9.e065152d8eae841p-3 m");
|
||||
CHECK(fmt::format("{:%.3aQ %q}", 1.2345678q_m) == "0x9.e06p-3 m");
|
||||
CHECK(fmt::format("{:%AQ %q}", 1.2345678q_m) == "0X9.E065152D8EAE841P-3 m");
|
||||
CHECK(fmt::format("{:%.3AQ %q}", 1.2345678q_m) == "0X9.E06P-3 m");
|
||||
#endif
|
||||
CHECK(fmt::format("{:%eQ %q}", 1.2345678q_m) == "1.234568e+00 m");
|
||||
CHECK(fmt::format("{:%.3eQ %q}", 1.2345678q_m) == "1.235e+00 m");
|
||||
CHECK(fmt::format("{:%EQ %q}", 1.2345678q_m) == "1.234568E+00 m");
|
||||
@@ -1007,10 +1022,17 @@ TEST_CASE("type specification", "[text][fmt]")
|
||||
CHECK(fmt::format("{:%xQ}", 42q_m) == "2a");
|
||||
CHECK(fmt::format("{:%XQ}", 42q_m) == "2A");
|
||||
|
||||
#ifdef COMP_MSVC
|
||||
CHECK(fmt::format("{:%aQ}", 1.2345678q_m) == "0x1.3c0ca2a5b1d5dp+0");
|
||||
CHECK(fmt::format("{:%.3aQ}", 1.2345678q_m) == "0x1.3c1p+0");
|
||||
CHECK(fmt::format("{:%AQ}", 1.2345678q_m) == "0X1.3C0CA2A5B1D5DP+0");
|
||||
CHECK(fmt::format("{:%.3AQ}", 1.2345678q_m) == "0X1.3C1P+0");
|
||||
#else
|
||||
CHECK(fmt::format("{:%aQ}", 1.2345678q_m) == "0x9.e065152d8eae841p-3");
|
||||
CHECK(fmt::format("{:%.3aQ}", 1.2345678q_m) == "0x9.e06p-3");
|
||||
CHECK(fmt::format("{:%AQ}", 1.2345678q_m) == "0X9.E065152D8EAE841P-3");
|
||||
CHECK(fmt::format("{:%.3AQ}", 1.2345678q_m) == "0X9.E06P-3");
|
||||
#endif
|
||||
CHECK(fmt::format("{:%eQ}", 1.2345678q_m) == "1.234568e+00");
|
||||
CHECK(fmt::format("{:%.3eQ}", 1.2345678q_m) == "1.235e+00");
|
||||
CHECK(fmt::format("{:%EQ}", 1.2345678q_m) == "1.234568E+00");
|
||||
|
@@ -20,6 +20,8 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
add_library(unit_tests_static
|
||||
cgs_test.cpp
|
||||
custom_rep_min_req_test.cpp
|
||||
@@ -43,5 +45,5 @@ add_library(unit_tests_static
|
||||
)
|
||||
target_link_libraries(unit_tests_static
|
||||
PRIVATE
|
||||
mp::units
|
||||
mp-units::mp-units
|
||||
)
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include "units/physical/si/frequency.h"
|
||||
#include "units/physical/si/speed.h"
|
||||
#include <chrono>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
using namespace units;
|
||||
@@ -65,7 +66,7 @@ template<typename T>
|
||||
struct expl_constructible : scalar_ops<expl_constructible<T>> {
|
||||
T value_{};
|
||||
expl_constructible() = default;
|
||||
constexpr expl_constructible(T v) : value_(std::move(v)) {}
|
||||
constexpr explicit expl_constructible(T v) : value_(std::move(v)) {}
|
||||
// no conversion to fundamental arithmetic types
|
||||
};
|
||||
|
||||
@@ -172,60 +173,60 @@ using namespace units::physical::si;
|
||||
// Quantity from Scalar
|
||||
// int <- int
|
||||
static_assert(length<metre, int>(expl_impl<int>(1)).count() == 1);
|
||||
// static_assert(length<metre, int>(impl_expl<int>(1)).count() == 1); // should not compile (not convertible)
|
||||
static_assert(!std::is_constructible_v<length<metre, int>, impl_expl<int>>);
|
||||
static_assert(length<metre, int>(int(impl_expl<int>(1))).count() == 1);
|
||||
// static_assert(length<metre, expl_impl<int>>(1).count() == expl_impl<int>{1}); // should not compile (not convertible)
|
||||
static_assert(!std::is_constructible_v<length<metre, expl_impl<int>>, int>);
|
||||
static_assert(length<metre, expl_impl<int>>(expl_impl<int>(1)).count() == expl_impl<int>{1});
|
||||
static_assert(length<metre, impl_expl<int>>(1).count() == impl_expl<int>{1});
|
||||
|
||||
// double <- double
|
||||
static_assert(length<metre, double>(expl_impl<double>(1.0)).count() == 1.0);
|
||||
// static_assert(length<metre, double>(impl_expl<double>(1.0)).count() == 1.0); // should not compile (not convertible)
|
||||
static_assert(!std::is_constructible_v<length<metre, double>, impl_expl<double>>);
|
||||
static_assert(length<metre, double>(double(impl_expl<double>(1.0))).count() == 1.0);
|
||||
// static_assert(length<metre, expl_impl<double>>(1.0).count() == expl_impl<double>{1.0}); // should not compile (not convertible)
|
||||
static_assert(!std::is_constructible_v<length<metre, expl_impl<double>>, double>);
|
||||
static_assert(length<metre, expl_impl<double>>(expl_impl<double>(1.0)).count() == expl_impl<double>{1.0});
|
||||
static_assert(length<metre, impl_expl<double>>(1.0).count() == impl_expl<double>{1.0});
|
||||
|
||||
// double <- int
|
||||
static_assert(length<metre, double>(expl_impl<int>(1)).count() == 1.0);
|
||||
// static_assert(length<metre, double>(impl_expl<int>(1)).count() == 1.0); // should not compile (not convertible)
|
||||
static_assert(!std::is_constructible_v<length<metre, double>, impl_expl<int>>);
|
||||
static_assert(length<metre, double>(int(impl_expl<int>(1))).count() == 1.0);
|
||||
// static_assert(length<metre, expl_impl<double>>(1).count() == expl_impl<double>{1}); // should not compile (not convertible)
|
||||
static_assert(!std::is_constructible_v<length<metre, expl_impl<double>>, int>);
|
||||
static_assert(length<metre, expl_impl<double>>(expl_impl<double>(1)).count() == expl_impl<double>{1});
|
||||
static_assert(length<metre, impl_expl<double>>(1).count() == impl_expl<double>{1.0});
|
||||
|
||||
// int <- double
|
||||
// static_assert(length<metre, int>(expl_impl<double>(1.0)).count() == 1); // should not compile (truncating conversion)
|
||||
// static_assert(length<metre, impl_expl<int>>(1.0).count() == impl_expl<int>{1}); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<length<metre, int>, expl_impl<double>>);
|
||||
static_assert(!std::is_constructible_v<length<metre, impl_expl<int>>, double>);
|
||||
|
||||
// Quantity from other Quantity with different Rep
|
||||
// int <- int
|
||||
static_assert(length<metre, int>(length<metre, expl_impl<int>>(expl_impl<int>(1))).count() == 1);
|
||||
// static_assert(length<metre, int>(length<metre, impl_expl<int>>(1)).count() == 1); // should not compile (not convertible)
|
||||
static_assert(!std::is_constructible_v<length<metre, int>, length<metre, impl_expl<int>>>);
|
||||
static_assert(length<metre, int>(quantity_cast<int>(length<metre, impl_expl<int>>(1))).count() == 1);
|
||||
// static_assert(length<metre, expl_impl<int>>(length<metre, int>(1)).count() == expl_impl<int>{1}); // should not compile (not convertible)
|
||||
static_assert(!std::is_constructible_v<length<metre, expl_impl<int>>, length<metre, int>>);
|
||||
static_assert(length<metre, expl_impl<int>>(quantity_cast<expl_impl<int>>(length<metre, int>(1))).count() == expl_impl<int>{1});
|
||||
static_assert(length<metre, impl_expl<int>>(length<metre, int>(1)).count() == impl_expl<int>{1});
|
||||
|
||||
// double <- double
|
||||
static_assert(length<metre, double>(length<metre, expl_impl<double>>(expl_impl<double>(1.0))).count() == 1.0);
|
||||
// static_assert(length<metre, double>(length<metre, impl_expl<double>>(1.0)).count() == 1.0); // should not compile (not convertible)
|
||||
static_assert(!std::is_constructible_v<length<metre, double>, length<metre, impl_expl<double>>>);
|
||||
static_assert(length<metre, double>(quantity_cast<double>(length<metre, impl_expl<double>>(1.0))).count() == 1.0);
|
||||
// static_assert(length<metre, expl_impl<double>>(length<metre>(1.0).count() == expl_impl<double>{1.0}); // should not compile (not convertible)
|
||||
static_assert(!std::is_constructible_v<length<metre, expl_impl<double>>, length<metre, double>>);
|
||||
static_assert(length<metre, expl_impl<double>>(quantity_cast<expl_impl<double>>(length<metre>(1.0))).count() == expl_impl<double>{1.0});
|
||||
static_assert(length<metre, impl_expl<double>>(length<metre>(1.0)).count() == impl_expl<double>{1.0});
|
||||
|
||||
// double <- int
|
||||
static_assert(length<metre, double>(length<metre, expl_impl<int>>(expl_impl<int>(1))).count() == 1.0);
|
||||
// static_assert(length<metre, double>(length<metre, impl_expl<int>>(1)).count() == 1.0); // should not compile (not convertible)
|
||||
static_assert(!std::is_constructible_v<length<metre, double>, length<metre, impl_expl<int>>>);
|
||||
static_assert(length<metre, double>(quantity_cast<int>(length<metre, impl_expl<int>>(1))).count() == 1.0);
|
||||
// static_assert(length<metre, expl_impl<double>>(length<metre, int>(1)).count() == expl_impl<double>{1}); // should not compile (not convertible)
|
||||
static_assert(!std::is_constructible_v<length<metre, expl_impl<double>>, length<metre, int>>);
|
||||
static_assert(length<metre, expl_impl<double>>(quantity_cast<expl_impl<double>>(length<metre, int>(1))).count() == expl_impl<double>{1});
|
||||
static_assert(length<metre, impl_expl<double>>(length<metre, int>(1)).count() == impl_expl<double>{1.0});
|
||||
|
||||
// int <- double
|
||||
// static_assert(length<metre, int>(length<metre, expl_impl<double>>(1.0)).count() == 1); // should not compile (truncating conversion)
|
||||
// static_assert(length<metre, impl_expl<int>>(length<metre, double>(1.0)).count() == impl_expl<int>{1}); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<length<metre, int>, length<metre, expl_impl<double>>>);
|
||||
static_assert(!std::is_constructible_v<length<metre, impl_expl<int>>, length<metre, double>>);
|
||||
|
||||
// unit conversions
|
||||
|
||||
@@ -236,43 +237,43 @@ static_assert(length<metre, impl_expl<int>>(length<kilometre, impl_expl<int>>(1)
|
||||
static_assert(length<metre, expl_impl<int>>(length<kilometre, expl_impl<int>>(expl_impl<int>(1))).count() == expl_impl<int>(1000));
|
||||
static_assert(length<metre, expl_expl<int>>(length<kilometre, expl_expl<int>>(expl_expl<int>(1))).count() == expl_expl<int>(1000));
|
||||
|
||||
// static_assert(length<kilometre, impl<int>>(length<metre, impl<int>>(2000)).count() == impl<int>(2)); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<length<kilometre, impl<int>>, length<metre, impl<int>>>);
|
||||
static_assert(length<kilometre, impl<int>>(quantity_cast<kilometre>(length<metre, impl<int>>(2000))).count() == impl<int>(2));
|
||||
// static_assert(length<kilometre, expl<int>>(length<metre, expl<int>>(expl<int>(2000))).count() == expl<int>(2)); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<length<kilometre, expl<int>>, length<metre, expl<int>>>);
|
||||
static_assert(length<kilometre, expl<int>>(quantity_cast<kilometre>(length<metre, expl<int>>(expl<int>(2000)))).count() == expl<int>(2));
|
||||
// static_assert(length<kilometre, impl_impl<int>>(length<metre, impl_impl<int>>(2000)).count() == impl_impl<int>(2)); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<length<kilometre, impl_impl<int>>, length<metre, impl_impl<int>>>);
|
||||
static_assert(length<kilometre, impl_impl<int>>(quantity_cast<kilometre>(length<metre, impl_impl<int>>(2000))).count() == impl_impl<int>(2));
|
||||
// static_assert(length<kilometre, impl_expl<int>>(length<metre, impl_expl<int>>(2000)).count() == impl_expl<int>(2)); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<length<kilometre, impl_expl<int>>, length<metre, impl_expl<int>>>);
|
||||
static_assert(length<kilometre, impl_expl<int>>(quantity_cast<kilometre>(length<metre, impl_expl<int>>(2000))).count() == impl_expl<int>(2));
|
||||
// static_assert(length<kilometre, expl_impl<int>>(length<metre, expl_impl<int>>(expl_impl<int>(2000))).count() == expl_impl<int>(2)); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<length<kilometre, expl_impl<int>>, length<metre, expl_impl<int>>>);
|
||||
static_assert(length<kilometre, expl_impl<int>>(quantity_cast<kilometre>(length<metre, expl_impl<int>>(expl_impl<int>(2000)))).count() == expl_impl<int>(2));
|
||||
// static_assert(length<kilometre, expl_expl<int>>(length<metre, expl_expl<int>>(expl_expl<int>(2000))).count() == expl_expl<int>(2)); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<length<kilometre, expl_expl<int>>, length<metre, expl_expl<int>>>);
|
||||
static_assert(length<kilometre, expl_expl<int>>(quantity_cast<kilometre>(length<metre, expl_expl<int>>(expl_expl<int>(2000)))).count() == expl_expl<int>(2));
|
||||
|
||||
// static_assert(speed<metre_per_second, impl<int>>(speed<kilometre_per_hour, impl<int>>(72)).count() == impl<int>(20)); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<speed<metre_per_second, impl<int>>, speed<kilometre_per_hour, impl<int>>>);
|
||||
static_assert(speed<metre_per_second, impl<int>>(quantity_cast<metre_per_second>(speed<kilometre_per_hour, impl<int>>(72))).count() == impl<int>(20));
|
||||
// static_assert(speed<metre_per_second, expl<int>>(speed<kilometre_per_hour, expl<int>>(expl(72))).count() == expl<int>(20)); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<speed<metre_per_second, expl<int>>, speed<kilometre_per_hour, expl<int>>>);
|
||||
static_assert(speed<metre_per_second, expl<int>>(quantity_cast<metre_per_second>(speed<kilometre_per_hour, expl<int>>(expl<int>(72)))).count() == expl<int>(20));
|
||||
// static_assert(speed<metre_per_second, impl_impl<int>>(speed<kilometre_per_hour, impl_impl<int>>(72)).count() == impl_impl<int>(20)); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<speed<metre_per_second, impl_impl<int>>, speed<kilometre_per_hour, impl_impl<int>>>);
|
||||
static_assert(speed<metre_per_second, impl_impl<int>>(quantity_cast<metre_per_second>(speed<kilometre_per_hour, impl_impl<int>>(72))).count() == impl_impl<int>(20));
|
||||
// static_assert(speed<metre_per_second, impl_expl<int>>(speed<kilometre_per_hour, impl_expl<int>>(72)).count() == impl_expl<int>(20)); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<speed<metre_per_second, impl_expl<int>>, speed<kilometre_per_hour, impl_expl<int>>>);
|
||||
static_assert(speed<metre_per_second, impl_expl<int>>(quantity_cast<metre_per_second>(speed<kilometre_per_hour, impl_expl<int>>(72))).count() == impl_expl<int>(20));
|
||||
// static_assert(speed<metre_per_second, expl_impl<int>>(speed<kilometre_per_hour, expl_impl<int>>(expl_impl(72))).count() == expl_impl<int>(20)); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<speed<metre_per_second, expl_impl<int>>, speed<kilometre_per_hour, expl_impl<int>>>);
|
||||
static_assert(speed<metre_per_second, expl_impl<int>>(quantity_cast<metre_per_second>(speed<kilometre_per_hour, expl_impl<int>>(expl_impl<int>(72)))).count() == expl_impl<int>(20));
|
||||
// static_assert(speed<metre_per_second, expl_expl<int>>(speed<kilometre_per_hour, expl_expl<int>>(expl_expl(72))).count() == expl_expl<int>(20)); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<speed<metre_per_second, expl_expl<int>>, speed<kilometre_per_hour, expl_expl<int>>>);
|
||||
static_assert(speed<metre_per_second, expl_expl<int>>(quantity_cast<metre_per_second>(speed<kilometre_per_hour, expl_expl<int>>(expl_expl<int>(72)))).count() == expl_expl<int>(20));
|
||||
|
||||
// static_assert(speed<kilometre_per_hour, impl<int>>(speed<metre_per_second, impl<int>>(20)).count() == impl<int>(72)); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<speed<kilometre_per_hour, impl<int>>, speed<metre_per_second, impl<int>>>);
|
||||
static_assert(speed<kilometre_per_hour, impl<int>>(quantity_cast<kilometre_per_hour>(speed<metre_per_second, impl<int>>(20))).count() == impl<int>(72));
|
||||
// static_assert(speed<kilometre_per_hour, expl<int>>(speed<metre_per_second, expl<int>>(expl<int>(20))).count() == expl<int>(72)); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<speed<kilometre_per_hour, expl<int>>, speed<metre_per_second, expl<int>>>);
|
||||
static_assert(speed<kilometre_per_hour, expl<int>>(quantity_cast<kilometre_per_hour>(speed<metre_per_second, expl<int>>(expl<int>(20)))).count() == expl<int>(72));
|
||||
// static_assert(speed<kilometre_per_hour, impl_impl<int>>(speed<metre_per_second, impl_impl<int>>(20)).count() == impl_impl<int>(72)); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<speed<kilometre_per_hour, impl_impl<int>>, speed<metre_per_second, impl_impl<int>>>);
|
||||
static_assert(speed<kilometre_per_hour, impl_impl<int>>(quantity_cast<kilometre_per_hour>(speed<metre_per_second, impl_impl<int>>(20))).count() == impl_impl<int>(72));
|
||||
// static_assert(speed<kilometre_per_hour, impl_expl<int>>(speed<metre_per_second, impl_expl<int>>(20)).count() == impl_expl<int>(72)); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<speed<kilometre_per_hour, impl_expl<int>>, speed<metre_per_second, impl_expl<int>>>);
|
||||
static_assert(speed<kilometre_per_hour, impl_expl<int>>(quantity_cast<kilometre_per_hour>(speed<metre_per_second, impl_expl<int>>(20))).count() == impl_expl<int>(72));
|
||||
// static_assert(speed<kilometre_per_hour, expl_impl<int>>(speed<metre_per_second, expl_impl<int>>(expl_impl<int>(20))).count() == expl_impl<int>(72)); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<speed<kilometre_per_hour, expl_impl<int>>, speed<metre_per_second, expl_impl<int>>>);
|
||||
static_assert(speed<kilometre_per_hour, expl_impl<int>>(quantity_cast<kilometre_per_hour>(speed<metre_per_second, expl_impl<int>>(expl_impl<int>(20)))).count() == expl_impl<int>(72));
|
||||
// static_assert(speed<kilometre_per_hour, expl_expl<int>>(speed<metre_per_second, expl_expl<int>>(expl_expl<int>(20))).count() == expl_expl<int>(72)); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<speed<kilometre_per_hour, expl_expl<int>>, speed<metre_per_second, expl_expl<int>>>);
|
||||
static_assert(speed<kilometre_per_hour, expl_expl<int>>(quantity_cast<kilometre_per_hour>(speed<metre_per_second, expl_expl<int>>(expl_expl<int>(20)))).count() == expl_expl<int>(72));
|
||||
|
||||
} // namespace
|
||||
|
@@ -47,7 +47,7 @@ concept invalid_types = requires
|
||||
!requires { typename quantity<metre, DimLength, double>; }; // reordered arguments
|
||||
};
|
||||
|
||||
static_assert(invalid_types<physical::si::dim_length>);
|
||||
static_assert(invalid_types<dim_length>);
|
||||
|
||||
// member types
|
||||
|
||||
@@ -226,14 +226,19 @@ static_assert(quantity_point_cast<int>(quantity_point(1.23q_m)).relative().count
|
||||
|
||||
// time
|
||||
|
||||
#if COMP_MSVC || COMP_GCC >= 10
|
||||
static_assert(!std::equality_comparable_with<quantity_point<dim_time, second, int>,
|
||||
quantity_point<dim_length, metre, int>>); // different dimensions
|
||||
#endif
|
||||
static_assert(quantity_point{1q_h} == quantity_point{3600q_s});
|
||||
|
||||
template<typename Metre>
|
||||
concept no_crossdimensional_equality = !requires
|
||||
{
|
||||
quantity_point(1q_s) == quantity_point(length<Metre, int>(1));
|
||||
};
|
||||
|
||||
static_assert(no_crossdimensional_equality<metre>);
|
||||
|
||||
// length
|
||||
|
||||
static_assert(quantity_point(1q_km) != quantity_point(1q_m));
|
||||
static_assert(quantity_point(1q_km) == quantity_point(1000q_m));
|
||||
static_assert(quantity_point(1q_km) + 1q_m == quantity_point(1001q_m));
|
||||
static_assert(1q_km + quantity_point(1q_m) == quantity_point(1001q_m));
|
||||
|
@@ -36,10 +36,15 @@ using namespace units::physical::si;
|
||||
|
||||
// class invariants
|
||||
|
||||
// constexpr quantity<si::dim_length, second, int> error(0); // should not compile (unit of a different dimension)
|
||||
// constexpr quantity<si::dim_length, metre, quantity<si::dim_length, metre, int>> error(0); // should not compile (quantity used as Rep)
|
||||
// constexpr quantity<metre, si::dim_length, double> error(0); // should not compile (reordered arguments)
|
||||
// constexpr quantity<si::dim_length, scaled_unit<ratio(-1, 1), metre>, int> error(0); // should not compile (negative unit ratio)
|
||||
template<typename DimLength>
|
||||
concept invalid_types = requires
|
||||
{
|
||||
!requires { typename quantity<DimLength, second, int>; }; // unit of a different dimension
|
||||
!requires { typename quantity<DimLength, metre, quantity<DimLength, metre, int>>; }; // quantity used as Rep
|
||||
!requires { typename quantity<metre, DimLength, double>; }; // reordered arguments
|
||||
};
|
||||
|
||||
static_assert(invalid_types<dim_length>);
|
||||
|
||||
// member types
|
||||
|
||||
@@ -56,18 +61,21 @@ static_assert(km.count() == 1000);
|
||||
static_assert(length<metre, int>(km).count() == km.count());
|
||||
|
||||
static_assert(length<metre, int>(1).count() == 1);
|
||||
// static_assert(length<metre, int>(1.0).count() == 1); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<length<metre, int>, double>); // truncating conversion
|
||||
static_assert(length<metre, double>(1.0).count() == 1.0);
|
||||
static_assert(length<metre, double>(1).count() == 1.0);
|
||||
static_assert(length<metre, double>(3.14).count() == 3.14);
|
||||
|
||||
static_assert(length<metre, int>(km).count() == 1000);
|
||||
// static_assert(length<metre, int>(length<metre, double>(3.14)).count() == 3); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<length<metre, int>,
|
||||
length<metre, double>>); // truncating conversion
|
||||
static_assert(length<metre, double>(1000.0q_m).count() == 1000.0);
|
||||
static_assert(length<metre, double>(km).count() == 1000.0);
|
||||
static_assert(length<metre, int>(1q_km).count() == 1000);
|
||||
// static_assert(length<metre, int>(1q_s).count() == 1); // should not compile (different dimensions)
|
||||
//static_assert(length<kilometre, int>(1010q_m).count() == 1); // should not compile (truncating conversion)
|
||||
static_assert(!std::is_constructible_v<length<metre, int>,
|
||||
physical::si::time<second, int>>); // different dimensions
|
||||
static_assert(!std::is_constructible_v<length<kilometre, int>,
|
||||
length<metre, int>>); // truncating conversion
|
||||
|
||||
// assignment operator
|
||||
|
||||
@@ -89,24 +97,22 @@ static_assert((-km).count() == -1000);
|
||||
static_assert((+(-km)).count() == -1000);
|
||||
static_assert((-(-km)).count() == 1000);
|
||||
|
||||
// binary member operators
|
||||
|
||||
static_assert([](auto v) {
|
||||
auto vv = v++;
|
||||
return std::make_pair(v, vv);
|
||||
}(km) == std::make_pair(length<metre, int>(1001), length<metre, int>(1000)));
|
||||
return std::pair(v, vv);
|
||||
}(km) == std::pair(length<metre, int>(1001), length<metre, int>(1000)));
|
||||
static_assert([](auto v) {
|
||||
auto vv = ++v;
|
||||
return std::make_pair(v, vv);
|
||||
}(km) == std::make_pair(length<metre, int>(1001), length<metre, int>(1001)));
|
||||
return std::pair(v, vv);
|
||||
}(km) == std::pair(length<metre, int>(1001), length<metre, int>(1001)));
|
||||
static_assert([](auto v) {
|
||||
auto vv = v--;
|
||||
return std::make_pair(v, vv);
|
||||
}(km) == std::make_pair(length<metre, int>(999), length<metre, int>(1000)));
|
||||
return std::pair(v, vv);
|
||||
}(km) == std::pair(length<metre, int>(999), length<metre, int>(1000)));
|
||||
static_assert([](auto v) {
|
||||
auto vv = --v;
|
||||
return std::make_pair(v, vv);
|
||||
}(km) == std::make_pair(length<metre, int>(999), length<metre, int>(999)));
|
||||
return std::pair(v, vv);
|
||||
}(km) == std::pair(length<metre, int>(999), length<metre, int>(999)));
|
||||
|
||||
// compound assignment
|
||||
|
||||
@@ -116,22 +122,29 @@ static_assert((1q_m *= 2).count() == 2);
|
||||
static_assert((2q_m /= 2).count() == 1);
|
||||
static_assert((7q_m %= 2).count() == 1);
|
||||
static_assert((7q_m %= 2q_m).count() == 1);
|
||||
// static_assert((7.m %= 2.).count() == 1); // should not compile (operation not allowed for floating-point types)
|
||||
// static_assert((7.m %= 2).count() == 1); // should not compile (operation not allowed for floating-point types)
|
||||
// static_assert((7q_m %= 2.).count() == 1); // should not compile (operation not allowed for floating-point types)
|
||||
static_assert((7q_m %= 2q_m).count() == 1);
|
||||
// static_assert((7.m %= 2.m).count() == 1); // should not compile (operation not allowed for floating-point types)
|
||||
// static_assert((7.m %= 2q_m).count() == 1); // should not compile (operation not allowed for floating-point types)
|
||||
// static_assert((7q_m %= 2.m).count() == 1); // should not compile (operation not allowed for floating-point types)
|
||||
|
||||
// static_assert(2q_m += 3.5q_m); // should not compile
|
||||
static_assert((2.5q_m += 3q_m).count() == 5.5);
|
||||
static_assert((2.5q_m += 3.5q_m).count() == 6);
|
||||
|
||||
// static_assert(2q_m *= 3.5); // should not compile
|
||||
static_assert((2.5q_m *= 3).count() == 7.5);
|
||||
static_assert((2.5q_m *= 3.5).count() == 8.75);
|
||||
|
||||
// operations not allowed for the respective quantities
|
||||
template<typename Metre>
|
||||
concept invalid_compound_assignments = requires()
|
||||
{
|
||||
!requires(length<Metre, double> l) { l %= 2.; };
|
||||
!requires(length<Metre, double> l) { l %= 2; };
|
||||
!requires(length<Metre, int> l) { l %= 2.; };
|
||||
!requires(length<Metre, double> l) { l %= 2.q_m; };
|
||||
!requires(length<Metre, double> l) { l %= 2q_m; };
|
||||
!requires(length<Metre, int> l) { l %= 2.q_m; };
|
||||
!requires(length<Metre, int> l) { l += 3.5q_m; };
|
||||
!requires(length<Metre, int> l) { l *= 3.5q_m; };
|
||||
};
|
||||
|
||||
static_assert(invalid_compound_assignments<metre>);
|
||||
|
||||
// non-member arithmetic operators
|
||||
|
||||
static_assert(is_same_v<decltype(length<metre, int>() + length<metre, double>()), length<metre, double>>);
|
||||
@@ -253,9 +266,13 @@ static_assert(quantity_cast<int>(1.23q_m).count() == 1);
|
||||
|
||||
// time
|
||||
|
||||
// static_assert(1q_s == 1q_m); // should not compile (different dimensions)
|
||||
static_assert(1q_h == 3600q_s);
|
||||
|
||||
template<typename Metre>
|
||||
concept no_crossdimensional_equality = !requires { 1q_s == length<Metre, int>(1); };
|
||||
|
||||
static_assert(no_crossdimensional_equality<metre>);
|
||||
|
||||
// length
|
||||
|
||||
static_assert(1q_km == 1000q_m);
|
||||
|
@@ -29,7 +29,6 @@ using namespace units;
|
||||
static_assert(ratio(2, 4) == ratio(1, 2));
|
||||
|
||||
// basic exponents tests
|
||||
// note use of ::type is required because template params are changed while stamping out template
|
||||
static_assert(ratio(2, 40, 1) == ratio(1, 20, 1));
|
||||
static_assert(ratio(20, 4, -1) == ratio(10, 2, -1));
|
||||
static_assert(ratio(200, 5) == ratio(20'000, 50, -1));
|
||||
|
@@ -40,7 +40,10 @@ struct hour : named_scaled_unit<hour, "h", no_prefix, ratio(36, 1, 2), second> {
|
||||
struct dim_time : base_dimension<"time", second> {};
|
||||
|
||||
struct kelvin : named_unit<kelvin, "K", no_prefix> {};
|
||||
// struct kilokelvin : prefixed_unit<kilokelvin, si::kilo, kelvin> {}; // should not compile (prefix not allowed for this reference unit)
|
||||
|
||||
#if COMP_GCC >= 10
|
||||
static_assert([]<Prefix P>(P) { return !requires { typename prefixed_unit<struct kilokelvin, P, kelvin>; }; }(si::kilo{})); // no prefix allowed
|
||||
#endif
|
||||
|
||||
struct metre_per_second : unit<metre_per_second> {};
|
||||
struct dim_speed : derived_dimension<dim_speed, metre_per_second, units::exp<dim_length, 1>, units::exp<dim_time, -1>> {};
|
||||
@@ -52,6 +55,10 @@ static_assert(is_same_v<downcast<scaled_unit<ratio(yard::ratio.num, yard::ratio.
|
||||
static_assert(is_same_v<downcast<scaled_unit<yard::ratio * ratio(1, 3), metre>>, foot>);
|
||||
static_assert(is_same_v<downcast<scaled_unit<kilometre::ratio / hour::ratio, metre_per_second>>, kilometre_per_hour>);
|
||||
|
||||
#if COMP_GCC >= 10
|
||||
static_assert([]<ratio R>() { return !requires { typename scaled_unit<R, metre>; }; }.template operator()<ratio(-1, 1)>()); // negative unit ratio
|
||||
#endif
|
||||
|
||||
static_assert(centimetre::symbol == "cm");
|
||||
static_assert(kilometre::symbol == "km");
|
||||
static_assert(kilometre_per_hour::symbol == "km/h");
|
||||
|
@@ -20,16 +20,14 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
project(test_package)
|
||||
|
||||
set(CMAKE_VERBOSE_MAKEFILE TRUE)
|
||||
|
||||
# set path to custom cmake modules
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../cmake")
|
||||
|
||||
# compilation options and flags used in a project development process
|
||||
include(common/cmake/scripts)
|
||||
include(common/scripts)
|
||||
|
||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||
conan_basic_setup(TARGETS)
|
||||
@@ -41,4 +39,4 @@ target_link_libraries(${PROJECT_NAME}_conan PRIVATE CONAN_PKG::mp-units)
|
||||
# test cmake-generated target
|
||||
find_package(mp-units CONFIG REQUIRED)
|
||||
add_executable(${PROJECT_NAME}_cmake test_package.cpp)
|
||||
target_link_libraries(${PROJECT_NAME}_cmake PRIVATE mp::units)
|
||||
target_link_libraries(${PROJECT_NAME}_cmake PRIVATE mp-units::mp-units)
|
||||
|
Reference in New Issue
Block a user