diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 293aa3af..cf54f05f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -50,6 +50,7 @@ endif() # check for C++ features check_cxx_feature_supported(__cpp_lib_format ${projectPrefix}LIB_FORMAT_SUPPORTED) check_cxx_feature_supported(__cpp_explicit_this_parameter ${projectPrefix}EXPLICIT_THIS_PARAMETER_SUPPORTED) +check_cxx_feature_supported("__cpp_constexpr_exceptions >= 202411L" ${projectPrefix}CONSTEXPR_EXCEPTIONS_SUPPORTED) # libc++ has a basic supports for std::format but does not set __cpp_lib_format # https://github.com/llvm/llvm-project/issues/77773 @@ -80,12 +81,16 @@ option(${projectPrefix}API_STD_FORMAT "Enable `std::format` support" ${${project option(${projectPrefix}API_NO_CRTP "Enable class definitions without CRTP idiom" ${${projectPrefix}EXPLICIT_THIS_PARAMETER_SUPPORTED} ) +option(${projectPrefix}API_THROWING_CONSTRAINTS "Enable throwing constraints" + ${projectPrefix}CONSTEXPR_EXCEPTIONS_SUPPORTED +) option(${projectPrefix}API_FREESTANDING "Builds only freestanding part of the library" OFF) set(${projectPrefix}API_CONTRACTS GSL-LITE CACHE STRING "Enable contract checking") check_cache_var_values(API_CONTRACTS NONE GSL-LITE MS-GSL) message(STATUS "${projectPrefix}API_STD_FORMAT: ${${projectPrefix}API_STD_FORMAT}") message(STATUS "${projectPrefix}API_NO_CRTP: ${${projectPrefix}API_NO_CRTP}") +message(STATUS "${projectPrefix}API_THROWING_CONSTRAINTS: ${${projectPrefix}API_THROWING_CONSTRAINTS}") message(STATUS "${projectPrefix}API_FREESTANDING: ${${projectPrefix}API_FREESTANDING}") message(STATUS "${projectPrefix}API_CONTRACTS: ${${projectPrefix}API_CONTRACTS}") diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 70b6892a..7a3c63b5 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -42,6 +42,7 @@ add_mp_units_module( include/mp-units/bits/text_tools.h include/mp-units/bits/type_list.h include/mp-units/bits/unit_magnitude.h + include/mp-units/bits/unsatisfied.h include/mp-units/ext/algorithm.h include/mp-units/ext/contracts.h include/mp-units/ext/fixed_string.h @@ -162,6 +163,14 @@ target_compile_definitions( ${projectPrefix}HOSTED=$> ) +# Throwing constraints +if(${projectPrefix}API_THROWING_CONSTRAINTS) + target_compile_definitions( + mp-units-core ${${projectPrefix}TARGET_SCOPE} + ${projectPrefix}API_THROWING_CONSTRAINTS=$ + ) +endif() + # https://github.com/llvm/llvm-project/issues/131410 if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 20 AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 20.2 diff --git a/src/core/include/mp-units/bits/unsatisfied.h b/src/core/include/mp-units/bits/unsatisfied.h new file mode 100644 index 00000000..0dc5aa3c --- /dev/null +++ b/src/core/include/mp-units/bits/unsatisfied.h @@ -0,0 +1,71 @@ +// 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 +#include // IWYU pragma: keep +#include + +#if MP_UNITS_API_THROWING_CONSTRAINTS +#ifndef MP_UNITS_IN_MODULE_INTERFACE +#ifdef MP_UNITS_IMPORT_STD +import std; +#else +#include +#include +#endif +#endif +#endif + +namespace mp_units::detail { + +#if MP_UNITS_API_THROWING_CONSTRAINTS + +#if __cpp_lib_constexpr_exceptions + +struct unsatisfied_constraints : std::logic_error { + consteval explicit unsatisfied_constraints(const std::string& msg) : std::logic_error(msg) {} + [[nodiscard]] constexpr const char* what() const noexcept override { return std::logic_error::what(); } +}; + +#else + +struct unsatisfied_constraints { + std::string msg; + [[nodiscard]] consteval const char* what() const noexcept { return msg.c_str(); } +}; + +#endif + +#endif + +template +[[nodiscard]] consteval bool unsatisfied([[maybe_unused]] Args&&... args) +{ +#if MP_UNITS_API_THROWING_CONSTRAINTS + throw unsatisfied_constraints{constexpr_format(FMT_COMPILE(Fmt.c_str()), std::forward(args)...)}; +#endif + return false; +} + +} // namespace mp_units::detail