diff --git a/.clang-tidy b/.clang-tidy index 9e1c87bc..33c41db5 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,23 +1,48 @@ ---- Checks: ' *, + -abseil-*, + -altera-*, + -cert-dcl37-c, + -cert-dcl50-cpp, + -cert-dcl51-cpp, + -cert-dcl58-cpp, + -cppcoreguidelines-avoid-const-or-ref-data-members, + -cppcoreguidelines-avoid-do-while, + -cppcoreguidelines-pro-bounds-constant-array-index, + -cppcoreguidelines-pro-bounds-pointer-arithmetic, + -cppcoreguidelines-pro-type-vararg, -llvm-header-guard, -llvm-include-order, - -bugprone-branch-clone, - -bugprone-reserved-identifier, - -modernize-use-trailing-return-type, + -llvm-namespace-comment, + -llvmlibc-*, -fuchsia-default-arguments-calls, + -fuchsia-default-arguments-declarations, + -fuchsia-multiple-inheritance, -fuchsia-overloaded-operator, -fuchsia-statically-constructed-objects, -fuchsia-trailing-return, - -*-special-member-functions, - -cppcoreguidelines-owning-memory, - -cert-err58-cpp, - -cert-dcl37-c, - -cert-dcl51-cpp + -google-readability-namespace-comments, + -google-readability-todo, + -google-runtime-int, + -hicpp-signed-bitwise, + -hicpp-vararg, + -misc-include-cleaner, + -modernize-use-trailing-return-type, + -modernize-use-designated-initializers, + -readability-identifier-length, + -readability-isolate-declaration, + -readability-magic-numbers, + -readability-static-accessed-through-instance, + -*-braces-around-statements, + -*-named-parameter, + -*-uppercase-literal-suffix, + -misc-no-recursion ' +CheckOptions: + - key: hicpp-signed-bitwise.IgnorePositiveIntegerLiterals + value: true + - key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic + value: true WarningsAsErrors: '*' HeaderFilterRegex: '.*' -AnalyzeTemporaryDtors: false FormatStyle: file -... diff --git a/CMakeLists.txt b/CMakeLists.txt index 2cb45efc..71e1818b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,12 @@ list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") set(projectPrefix MP_UNITS_) option(${projectPrefix}DEV_BUILD_LA "Build code depending on the linear algebra library" ON) +option(${projectPrefix}DEV_IWYU "Enables include-what-you-use" OFF) +option(${projectPrefix}DEV_CLANG_TIDY "Enables clang-tidy" OFF) + message(STATUS "${projectPrefix}DEV_BUILD_LA: ${${projectPrefix}DEV_BUILD_LA}") +message(STATUS "${projectPrefix}DEV_IWYU: ${${projectPrefix}DEV_IWYU}") +message(STATUS "${projectPrefix}DEV_CLANG_TIDY: ${${projectPrefix}DEV_CLANG_TIDY}") # make sure that the file is being used as an entry point include(modern_project_structure) @@ -38,9 +43,6 @@ ensure_entry_point() include(ccache) enable_ccache(BASE_DIR ${PROJECT_SOURCE_DIR}) -# enable include-what-you-use -option(${projectPrefix}DEV_IWYU "Enables include-what-you-use" OFF) - if(${projectPrefix}DEV_IWYU) set(${projectPrefix}BUILD_AS_SYSTEM_HEADERS ON) @@ -51,6 +53,9 @@ if(${projectPrefix}DEV_IWYU) MAX_LINE_LENGTH 120 NO_COMMENTS ) +elseif(${projectPrefix}DEV_CLANG_TIDY) + include(static_analysis) + enable_clang_tidy() else() # set restrictive compilation warnings # (some gcc warnings are not recognized by IWYU which is based on clang) @@ -58,8 +63,6 @@ else() set_warnings() endif() -# enable_clang_tidy() - # add project code add_subdirectory(src) diff --git a/cmake/static_analysis.cmake b/cmake/static_analysis.cmake index 28f00e9c..d91522fa 100644 --- a/cmake/static_analysis.cmake +++ b/cmake/static_analysis.cmake @@ -20,7 +20,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.3) +cmake_minimum_required(VERSION 3.5) macro(enable_clang_tidy) find_program(clang_tidy_cmd NAMES "clang-tidy") diff --git a/example/.clang-tidy b/example/.clang-tidy new file mode 100644 index 00000000..ee273830 --- /dev/null +++ b/example/.clang-tidy @@ -0,0 +1,6 @@ +Checks: ' + -bugprone-exception-escape, + -cppcoreguidelines-avoid-magic-numbers, + -google-build-using-namespace +' +InheritParentConfig: true diff --git a/example/conversion_factor.cpp b/example/conversion_factor.cpp index 303d36e0..b95c018e 100644 --- a/example/conversion_factor.cpp +++ b/example/conversion_factor.cpp @@ -35,7 +35,7 @@ namespace { template requires std::constructible_from -inline constexpr double conversion_factor(Target, Source) +constexpr double conversion_factor(Target, Source) { return (1. * Source::reference).force_numerical_value_in(Target::unit); } diff --git a/example/currency.cpp b/example/currency.cpp index c81786fb..a638fe86 100644 --- a/example/currency.cpp +++ b/example/currency.cpp @@ -58,7 +58,7 @@ inline constexpr auto JPY = japanese_jen; static_assert(!std::equality_comparable_with, quantity>); -#if 0 +#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if) // if you have only a few currencies to handle template @@ -76,12 +76,12 @@ template template [[nodiscard]] double exchange_rate() { - static std::map, double> rates = { + static const std::map, double> rates = { {{"USD", "EUR"}, 0.9215}, {{"EUR", "USD"}, 1.0848}, // ... }; - return rates[std::make_pair(to_string_view(From), to_string_view(To))]; + return rates.at(std::make_pair(to_string_view(From), to_string_view(To))); } #endif @@ -103,8 +103,8 @@ int main() { using namespace unit_symbols; - quantity_point price_usd{100 * USD}; - quantity_point price_euro = exchange_to(price_usd); + const quantity_point price_usd{100 * USD}; + const quantity_point price_euro = exchange_to(price_usd); std::cout << price_usd.quantity_from_zero() << " -> " << price_euro.quantity_from_zero() << "\n"; // std::cout << price_usd.quantity_from_zero() + price_euro.quantity_from_zero() << "\n"; // does diff --git a/example/glide_computer.cpp b/example/glide_computer.cpp index eb7b26be..533002a1 100644 --- a/example/glide_computer.cpp +++ b/example/glide_computer.cpp @@ -181,7 +181,7 @@ void example() for (const auto& g : gliders) { for (const auto& c : weather_conditions) { - std::string txt = "Scenario: Glider = " + g.name + ", Weather = " + c.first; + const std::string txt = "Scenario: Glider = " + g.name + ", Weather = " + c.first; std::cout << txt << "\n"; std::cout << MP_UNITS_STD_FMT::format("{0:=^{1}}\n\n", "", txt.size()); diff --git a/example/glide_computer_lib/include/glide_computer_lib.h b/example/glide_computer_lib/include/glide_computer_lib.h index bb04a7b3..8f26bb4c 100644 --- a/example/glide_computer_lib/include/glide_computer_lib.h +++ b/example/glide_computer_lib/include/glide_computer_lib.h @@ -111,10 +111,11 @@ public: const waypoint* end_; distance length_ = geographic::spherical_distance(begin().pos, end().pos); public: + // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) leg(const waypoint& b, const waypoint& e) noexcept : begin_(&b), end_(&e) {} - constexpr const waypoint& begin() const { return *begin_; }; - constexpr const waypoint& end() const { return *end_; } - constexpr distance get_distance() const { return length_; } + [[nodiscard]] constexpr const waypoint& begin() const { return *begin_; }; + [[nodiscard]] constexpr const waypoint& end() const { return *end_; } + [[nodiscard]] constexpr distance get_distance() const { return length_; } }; using legs = std::vector; @@ -126,19 +127,19 @@ public: task(std::initializer_list wpts) : waypoints_(wpts) {} - const waypoints& get_waypoints() const { return waypoints_; } - const legs& get_legs() const { return legs_; } + [[nodiscard]] const waypoints& get_waypoints() const { return waypoints_; } + [[nodiscard]] const legs& get_legs() const { return legs_; } - const waypoint& get_start() const { return waypoints_.front(); } - const waypoint& get_finish() const { return waypoints_.back(); } + [[nodiscard]] const waypoint& get_start() const { return waypoints_.front(); } + [[nodiscard]] const waypoint& get_finish() const { return waypoints_.back(); } - distance get_distance() const { return length_; } + [[nodiscard]] distance get_distance() const { return length_; } - distance get_leg_dist_offset(std::size_t leg_index) const + [[nodiscard]] distance get_leg_dist_offset(std::size_t leg_index) const { return leg_index == 0 ? distance{} : leg_total_distances_[leg_index - 1]; } - std::size_t get_leg_index(distance dist) const + [[nodiscard]] std::size_t get_leg_index(distance dist) const { return static_cast( std::ranges::distance(leg_total_distances_.cbegin(), std::ranges::lower_bound(leg_total_distances_, dist))); diff --git a/example/include/geographic.h b/example/include/geographic.h index e1bfe77f..5366303c 100644 --- a/example/include/geographic.h +++ b/example/include/geographic.h @@ -84,20 +84,14 @@ template std::basic_ostream& operator<<(std::basic_ostream& os, const latitude& lat) { const auto& q = lat.quantity_ref_from(geographic::equator); - if (is_gteq_zero(q)) - return os << q << " N"; - else - return os << -q << " S"; + return (is_gteq_zero(q)) ? (os << q << " N") : (os << -q << " S"); } template std::basic_ostream& operator<<(std::basic_ostream& os, const longitude& lon) { const auto& q = lon.quantity_ref_from(geographic::prime_meridian); - if (is_gteq_zero(q)) - return os << q << " E"; - else - return os << -q << " W"; + return (is_gteq_zero(q)) ? (os << q << " E") : (os << -q << " W"); } inline namespace literals { @@ -174,6 +168,7 @@ struct position { }; template +// NOLINTNEXTLINE(bugprone-easily-swappable-parameters) distance spherical_distance(position from, position to) { using namespace mp_units; diff --git a/example/include/validated_type.h b/example/include/validated_type.h index 738c42e6..8b05aa8f 100644 --- a/example/include/validated_type.h +++ b/example/include/validated_type.h @@ -32,7 +32,6 @@ import mp_units.core; #else #include -#include #include #endif @@ -82,12 +81,14 @@ public: #else + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) constexpr explicit(false) operator T() const& noexcept(std::is_nothrow_copy_constructible_v) requires std::copyable { return value_; } + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) constexpr explicit(false) operator T() && noexcept(std::is_nothrow_move_constructible_v) { return std::move(value_); @@ -96,14 +97,14 @@ public: #endif constexpr T& value() & noexcept = delete; - constexpr const T& value() const& noexcept { return value_; } - constexpr T&& value() && noexcept { return std::move(value_); } - constexpr const T&& value() const&& noexcept { return std::move(value_); } + [[nodiscard]] constexpr const T& value() const& noexcept { return value_; } + [[nodiscard]] constexpr T&& value() && noexcept { return std::move(value_); } + [[nodiscard]] constexpr const T&& value() const&& noexcept { return std::move(value_); } - bool operator==(const validated_type&) const + [[nodiscard]] bool operator==(const validated_type&) const requires std::equality_comparable = default; - auto operator<=>(const validated_type&) const + [[nodiscard]] auto operator<=>(const validated_type&) const requires std::three_way_comparable = default; }; diff --git a/example/measurement.cpp b/example/measurement.cpp index 1609c158..d8bd2297 100644 --- a/example/measurement.cpp +++ b/example/measurement.cpp @@ -45,11 +45,13 @@ public: measurement() = default; - constexpr explicit measurement(value_type val, const value_type& err = {}) : value_(std::move(val)) + // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) + constexpr explicit measurement(value_type val, const value_type& err = {}) : + value_(std::move(val)), uncertainty_([&] { + using namespace std; + return abs(err); + }()) { - // it sucks that using declaration cannot be provided for a constructor initializer list - using namespace std; - uncertainty_ = abs(err); } [[nodiscard]] constexpr const value_type& value() const { return value_; } diff --git a/example/spectroscopy_units.cpp b/example/spectroscopy_units.cpp index 96562417..ae12080b 100644 --- a/example/spectroscopy_units.cpp +++ b/example/spectroscopy_units.cpp @@ -40,8 +40,6 @@ using namespace mp_units; using mp_units::si::unit_symbols::cm; using mp_units::si::unit_symbols::eV; using mp_units::si::unit_symbols::K; -using mp_units::si::unit_symbols::kJ; -using mp_units::si::unit_symbols::mol; using mp_units::si::unit_symbols::THz; using mp_units::si::unit_symbols::um; diff --git a/example/total_energy.cpp b/example/total_energy.cpp index caba813d..63f26f44 100644 --- a/example/total_energy.cpp +++ b/example/total_energy.cpp @@ -52,7 +52,7 @@ void si_example() using namespace mp_units::si::unit_symbols; constexpr Unit auto GeV = si::giga; constexpr quantity c = 1. * si::si2019::speed_of_light_in_vacuum; - quantity c2 = pow<2>(c); + const quantity c2 = pow<2>(c); const quantity p1 = isq::momentum(4. * GeV / c); const QuantityOf auto m1 = 3. * GeV / c2; diff --git a/example/unmanned_aerial_vehicle.cpp b/example/unmanned_aerial_vehicle.cpp index e8976e93..23b05ccf 100644 --- a/example/unmanned_aerial_vehicle.cpp +++ b/example/unmanned_aerial_vehicle.cpp @@ -24,6 +24,7 @@ #include "ranged_representation.h" #include #include +#include #include #include #ifdef MP_UNITS_MODULES @@ -39,14 +40,14 @@ using namespace geographic; // **** HAE **** -enum class earth_gravity_model { egm84_15, egm95_5, egm2008_1 }; +enum class earth_gravity_model : std::int8_t { egm84_15, egm95_5, egm2008_1 }; template struct height_above_ellipsoid_t : absolute_point_origin, isq::altitude> { static constexpr earth_gravity_model egm = M; }; template -inline constexpr height_above_ellipsoid_t height_above_ellipsoid; +inline constexpr height_above_ellipsoid_t height_above_ellipsoid; // NOLINT(google-readability-casting) template using hae_altitude = quantity_point>; @@ -141,12 +142,12 @@ class unmanned_aerial_vehicle { msl_altitude launch_ = current_; public: void take_off(msl_altitude alt) { launch_ = alt; } - msl_altitude take_off() const { return launch_; } + [[nodiscard]] msl_altitude take_off() const { return launch_; } void current(msl_altitude alt) { current_ = alt; } - msl_altitude current() const { return current_; } + [[nodiscard]] msl_altitude current() const { return current_; } - hal_altitude hal() const { return height_above_launch + (current_ - launch_); } + [[nodiscard]] hal_altitude hal() const { return height_above_launch + (current_ - launch_); } }; @@ -160,7 +161,7 @@ int main() uav.current(mean_sea_level + 10'000 * ft); std::cout << MP_UNITS_STD_FMT::format("hal = {::N[.2f]}\n", uav.hal()); - msl_altitude ground_level = mean_sea_level + 123 * m; + const msl_altitude ground_level = mean_sea_level + 123 * m; std::cout << MP_UNITS_STD_FMT::format("agl = {::N[.2f]}\n", uav.current() - ground_level); struct waypoint { @@ -169,7 +170,7 @@ int main() msl_altitude msl_alt; }; - waypoint wpt = {"EPPR", {54.24772_N, 18.6745_E}, mean_sea_level + 16. * ft}; + const waypoint wpt = {"EPPR", {54.24772_N, 18.6745_E}, mean_sea_level + 16. * ft}; std::cout << MP_UNITS_STD_FMT::format("{}: {} {}, {::N[.2f]}, {::N[.2f]}\n", wpt.name, wpt.pos.lat, wpt.pos.lon, wpt.msl_alt, to_hae(wpt.msl_alt, wpt.pos)); } diff --git a/src/core/include/mp-units/bits/fmt.h b/src/core/include/mp-units/bits/fmt.h index 8ffb7284..16d98363 100644 --- a/src/core/include/mp-units/bits/fmt.h +++ b/src/core/include/mp-units/bits/fmt.h @@ -27,13 +27,16 @@ // // For the license information refer to format.h. +// NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic, cppcoreguidelines-pro-type-union-access) #pragma once #include +#include #ifndef MP_UNITS_IN_MODULE_INTERFACE #include #include +#include #include #include #endif @@ -42,8 +45,8 @@ namespace mp_units::detail { -enum class fmt_align { none, left, right, center, numeric }; -enum class fmt_arg_id_kind { +enum class fmt_align : std::int8_t { none, left, right, center, numeric }; +enum class fmt_arg_id_kind : std::int8_t { none, #if MP_UNITS_USE_FMTLIB name, @@ -61,7 +64,7 @@ struct fmt_arg_ref { #endif constexpr value() {} - constexpr value(int idx) : index(idx) {} + constexpr explicit value(int idx) : index(idx) {} #if MP_UNITS_USE_FMTLIB constexpr value(std::basic_string_view n) : name(n) {} #endif @@ -86,7 +89,7 @@ struct fill_t { private: static constexpr size_t max_size = 4 / sizeof(Char); // At most one codepoint (so one char32_t or four utf-8 char8_t) - Char data_[max_size] = {Char{' '}}; + std::array data_ = {Char{' '}}; unsigned char size_ = 1; public: @@ -100,15 +103,15 @@ public: } [[nodiscard]] constexpr size_t size() const { return size_; } - [[nodiscard]] constexpr const Char* data() const { return data_; } + [[nodiscard]] constexpr const Char* data() const { return data_.data(); } [[nodiscard]] constexpr Char& operator[](size_t index) { return data_[index]; } [[nodiscard]] constexpr const Char& operator[](size_t index) const { return data_[index]; } }; template -inline constexpr bool is_integer = std::is_integral::value && !std::is_same::value && - !std::is_same::value && !std::is_same::value; +inline constexpr bool is_integer = + std::is_integral_v && !std::is_same_v && !std::is_same_v && !std::is_same_v; // Converts a character to ASCII. Returns a number > 127 on conversion failure. template @@ -211,7 +214,7 @@ template } template -[[nodiscard]] constexpr const Char* do_parse_arg_id(const Char* begin, const Char* end, Handler&& handler) +[[nodiscard]] constexpr const Char* do_parse_arg_id(const Char* begin, const Char* end, Handler& handler) { Char c = *begin; if (c >= '0' && c <= '9') { @@ -223,8 +226,7 @@ template ++begin; if (begin == end || (*begin != '}' && *begin != ':')) MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("invalid format string")); - else - handler.on_index(index); + handler.on_index(index); return begin; } if (c == '%') return begin; // mp-units extension @@ -246,7 +248,7 @@ template } template -[[nodiscard]] constexpr const Char* parse_arg_id(const Char* begin, const Char* end, Handler&& handler) +[[nodiscard]] constexpr const Char* parse_arg_id(const Char* begin, const Char* end, Handler& handler) { gsl_Expects(begin != end); Char c = *begin; @@ -262,7 +264,7 @@ struct dynamic_spec_id_handler { constexpr void on_auto() { - int id = MP_UNITS_FMT_FROM_ARG_ID(ctx.next_arg_id()); + const int id = MP_UNITS_FMT_FROM_ARG_ID(ctx.next_arg_id()); ref = fmt_arg_ref(id); #if MP_UNITS_USE_FMTLIB || __cpp_lib_format >= 202305L ctx.check_dynamic_spec(id); @@ -292,7 +294,7 @@ template { gsl_Expects(begin != end); if ('0' <= *begin && *begin <= '9') { - int val = ::mp_units::detail::parse_nonnegative_int(begin, end, -1); + const int val = ::mp_units::detail::parse_nonnegative_int(begin, end, -1); if (val != -1) value = val; else @@ -312,9 +314,9 @@ template constexpr int code_point_length(It begin) { if constexpr (sizeof(std::iter_value_t) != 1) return 1; - constexpr char lengths[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 0}; - int len = lengths[static_cast(*begin) >> 3]; + constexpr std::array lengths = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 0}; + const int len = lengths[static_cast(*begin) >> 3]; // Compute the pointer to the next character early so that the next // iteration can start working on the next character. Neither Clang @@ -357,9 +359,8 @@ template ++begin; } break; - } else if (p == begin) { - break; } + if (p == begin) break; p = begin; } if (align == fmt_align::none) align = default_align; // mp-units extension @@ -368,3 +369,4 @@ template } } // namespace mp_units::detail +// NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic, cppcoreguidelines-pro-type-union-access) diff --git a/src/core/include/mp-units/bits/hacks.h b/src/core/include/mp-units/bits/hacks.h index 38e729d9..f1d9b837 100644 --- a/src/core/include/mp-units/bits/hacks.h +++ b/src/core/include/mp-units/bits/hacks.h @@ -20,6 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +// NOLINTBEGIN(bugprone-reserved-identifier, cppcoreguidelines-macro-usage) #pragma once #ifndef MP_UNITS_IN_MODULE_INTERFACE @@ -122,3 +123,4 @@ #define MP_UNITS_API_NO_CRTP 1 #endif +// NOLINTEND(bugprone-reserved-identifier, cppcoreguidelines-macro-usage) diff --git a/src/core/include/mp-units/bits/ratio.h b/src/core/include/mp-units/bits/ratio.h index 872a82ce..bcd5ca69 100644 --- a/src/core/include/mp-units/bits/ratio.h +++ b/src/core/include/mp-units/bits/ratio.h @@ -42,17 +42,18 @@ template [[nodiscard]] consteval std::intmax_t safe_multiply(std::intmax_t lhs, std::intmax_t rhs) { - constexpr std::intmax_t c = std::uintmax_t(1) << (sizeof(std::intmax_t) * 4); + constexpr std::intmax_t c = std::uintmax_t{1} << (sizeof(std::intmax_t) * 4); const std::intmax_t a0 = abs(lhs) % c; const std::intmax_t a1 = abs(lhs) / c; const std::intmax_t b0 = abs(rhs) % c; const std::intmax_t b1 = abs(rhs) / c; - gsl_Assert(a1 == 0 || b1 == 0); // overflow in multiplication - gsl_Assert(a0 * b1 + b0 * a1 < (c >> 1)); // overflow in multiplication - gsl_Assert(b0 * a0 <= INTMAX_MAX); // overflow in multiplication - gsl_Assert((a0 * b1 + b0 * a1) * c <= INTMAX_MAX - b0 * a0); // overflow in multiplication + // overflow in multiplication + gsl_Assert(a1 == 0 || b1 == 0); + gsl_Assert(a0 * b1 + b0 * a1 < (c >> 1)); // NOLINT(hicpp-signed-bitwise) + gsl_Assert(b0 * a0 <= INTMAX_MAX); + gsl_Assert((a0 * b1 + b0 * a1) * c <= INTMAX_MAX - b0 * a0); return lhs * rhs; } @@ -68,13 +69,14 @@ MP_UNITS_EXPORT struct ratio { std::intmax_t num; std::intmax_t den; + // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) MP_UNITS_CONSTEVAL explicit(false) ratio(std::intmax_t n, std::intmax_t d = 1) : num{n}, den{d} { gsl_Expects(den != 0); if (num == 0) den = 1; else { - std::intmax_t gcd = std::gcd(num, den); + const std::intmax_t gcd = std::gcd(num, den); num = num * (den < 0 ? -1 : 1) / gcd; den = detail::abs(den) / gcd; } @@ -114,9 +116,9 @@ MP_UNITS_EXPORT struct ratio { gsl_Assert(std::numeric_limits::max() / r2.num > r1.den); gsl_Assert(std::numeric_limits::max() / r1.den > r2.den); - std::intmax_t num = std::gcd(r1.num * r2.den, r2.num * r1.den); - std::intmax_t den = r1.den * r2.den; - std::intmax_t gcd = std::gcd(num, den); + const std::intmax_t num = std::gcd(r1.num * r2.den, r2.num * r1.den); + const std::intmax_t den = r1.den * r2.den; + const std::intmax_t gcd = std::gcd(num, den); return ratio{num / gcd, den / gcd}; } diff --git a/src/core/include/mp-units/bits/text_tools.h b/src/core/include/mp-units/bits/text_tools.h index a2691b74..0f79b0ad 100644 --- a/src/core/include/mp-units/bits/text_tools.h +++ b/src/core/include/mp-units/bits/text_tools.h @@ -97,7 +97,7 @@ constexpr Out copy(const symbol_text& txt, text_encoding encoding, Out out if constexpr (is_same_v) return copy(txt.unicode(), out).out; else if constexpr (is_same_v) { - for (char8_t ch : txt.unicode()) *out++ = static_cast(ch); + for (const char8_t ch : txt.unicode()) *out++ = static_cast(ch); return out; } else throw std::invalid_argument("Unicode text can't be copied to CharT output"); @@ -130,20 +130,17 @@ constexpr Out copy_symbol_exponent(text_encoding encoding, bool negative_power, constexpr auto txt = symbol_text("^-(") + regular() + symbol_text("/") + regular() + symbol_text(")"); return copy(txt, encoding, out); - } else { - constexpr auto txt = - symbol_text("^(") + regular() + symbol_text("/") + regular() + symbol_text(")"); - return copy(txt, encoding, out); } + constexpr auto txt = symbol_text("^(") + regular() + symbol_text("/") + regular() + symbol_text(")"); + return copy(txt, encoding, out); } else if constexpr (r.num != 1) { // add exponent part if (negative_power) { constexpr auto txt = superscript<-r.num>(); return copy(txt, encoding, out); - } else { - constexpr auto txt = superscript(); - return copy(txt, encoding, out); } + constexpr auto txt = superscript(); + return copy(txt, encoding, out); } } diff --git a/src/core/include/mp-units/compat_macros.h b/src/core/include/mp-units/compat_macros.h index e1d0c114..227551c7 100644 --- a/src/core/include/mp-units/compat_macros.h +++ b/src/core/include/mp-units/compat_macros.h @@ -21,7 +21,7 @@ // SOFTWARE. // IWYU pragma: always_keep - +// NOLINTBEGIN(cppcoreguidelines-macro-usage) #pragma once #include @@ -103,3 +103,4 @@ MP_UNITS_DIAGNOSTIC_POP // IWYU pragma: end_exports #endif +// NOLINTEND(cppcoreguidelines-macro-usage) diff --git a/src/core/include/mp-units/ext/algorithm.h b/src/core/include/mp-units/ext/algorithm.h index 576f1205..6c60443c 100644 --- a/src/core/include/mp-units/ext/algorithm.h +++ b/src/core/include/mp-units/ext/algorithm.h @@ -36,6 +36,24 @@ namespace mp_units::detail { +template +constexpr InputIt find_if(InputIt first, InputIt last, UnaryPred p) +{ + for (; first != last; ++first) + if (p(*first)) return first; + + return last; +} + +template +constexpr InputIt find_if_not(InputIt first, InputIt last, UnaryPred q) +{ + for (; first != last; ++first) + if (!q(*first)) return first; + + return last; +} + template constexpr InputIt find_first_of(InputIt first, InputIt last, ForwardIt s_first, ForwardIt s_last) { @@ -49,6 +67,12 @@ constexpr InputIt find_first_of(InputIt first, InputIt last, ForwardIt s_first, return last; } +template +constexpr bool all_of(InputIt first, InputIt last, UnaryPred p) +{ + return find_if_not(first, last, p) == last; +} + template constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2) { @@ -61,30 +85,31 @@ constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2) } template -constexpr auto lexicographical_compare_three_way(I1 f1, I1 l1, I2 f2, I2 l2, Cmp comp) -> decltype(comp(*f1, *f2)) +constexpr auto lexicographical_compare_three_way(I1 first1, I1 last1, I2 first2, I2 last2, Cmp comp) + -> decltype(comp(*first1, *first2)) { - using ret_t = decltype(comp(*f1, *f2)); + using ret_t = decltype(comp(*first1, *first2)); static_assert(std::disjunction_v, std::is_same, std::is_same>, "The return type must be a comparison category type."); - bool exhaust1 = (f1 == l1); - bool exhaust2 = (f2 == l2); + bool exhaust1 = (first1 == last1); + bool exhaust2 = (first2 == last2); MP_UNITS_DIAGNOSTIC_PUSH MP_UNITS_DIAGNOSTIC_IGNORE_ZERO_AS_NULLPOINTER_CONSTANT - for (; !exhaust1 && !exhaust2; exhaust1 = (++f1 == l1), exhaust2 = (++f2 == l2)) - if (auto c = comp(*f1, *f2); c != 0) return c; + for (; !exhaust1 && !exhaust2; exhaust1 = (++first1 == last1), exhaust2 = (++first2 == last2)) + if (auto c = comp(*first1, *first2); c != 0) return c; MP_UNITS_DIAGNOSTIC_POP - return !exhaust1 ? std::strong_ordering::greater - : !exhaust2 ? std::strong_ordering::less - : std::strong_ordering::equal; + if (!exhaust1) return std::strong_ordering::greater; + if (!exhaust2) return std::strong_ordering::less; + return std::strong_ordering::equal; } template -constexpr auto lexicographical_compare_three_way(I1 f1, I1 l1, I2 f2, I2 l2) +constexpr auto lexicographical_compare_three_way(I1 first1, I1 last1, I2 first2, I2 last2) { - return ::mp_units::detail::lexicographical_compare_three_way(f1, l1, f2, l2, std::compare_three_way()); + return ::mp_units::detail::lexicographical_compare_three_way(first1, last1, first2, last2, std::compare_three_way()); } template diff --git a/src/core/include/mp-units/ext/fixed_string.h b/src/core/include/mp-units/ext/fixed_string.h index 2ff4c745..f093d2e8 100644 --- a/src/core/include/mp-units/ext/fixed_string.h +++ b/src/core/include/mp-units/ext/fixed_string.h @@ -23,6 +23,7 @@ // To be replaced with: // P3094: std::basic_fixed_string +// NOLINTBEGIN(*-avoid-c-arrays) #pragma once // TODO use when moved to C++20 modules (parsing takes too long for each translation unit) @@ -84,7 +85,7 @@ struct basic_fixed_string { [[nodiscard]] constexpr bool empty() const noexcept { return N == 0; } [[nodiscard]] constexpr size_type size() const noexcept { return N; } - [[nodiscard]] constexpr const_pointer data() const noexcept { return data_; } + [[nodiscard]] constexpr const_pointer data() const noexcept { return static_cast(data_); } [[nodiscard]] constexpr const CharT* c_str() const noexcept { return data(); } [[nodiscard]] constexpr value_type operator[](size_type index) const noexcept { @@ -97,7 +98,8 @@ struct basic_fixed_string { [[nodiscard]] constexpr const_iterator end() const noexcept { return data() + size(); } [[nodiscard]] constexpr const_iterator cend() const noexcept { return data() + size(); } - [[nodiscard]] constexpr operator std::basic_string_view() const noexcept + // NOLINTNEXTLINE(*-explicit-conversions, google-explicit-constructor) + [[nodiscard]] constexpr explicit(false) operator std::basic_string_view() const noexcept { return std::basic_string_view(cbegin(), cend()); } @@ -169,3 +171,4 @@ struct MP_UNITS_STD_FMT::formatter> : for return formatter>::format(std::basic_string_view(str), ctx); } }; +// NOLINTEND(*-avoid-c-arrays) diff --git a/src/core/include/mp-units/ext/prime.h b/src/core/include/mp-units/ext/prime.h index e51f9411..31d4f2cc 100644 --- a/src/core/include/mp-units/ext/prime.h +++ b/src/core/include/mp-units/ext/prime.h @@ -65,7 +65,7 @@ namespace mp_units::detail { template [[nodiscard]] consteval std::array first_n_primes() { - std::array primes; + std::array primes{}; primes[0] = 2; for (std::size_t i = 1; i < N; ++i) { primes[i] = primes[i - 1] + 1; @@ -77,7 +77,7 @@ template } template -consteval void call_for_coprimes_up_to(std::uintmax_t n, const std::array& basis, Callable&& call) +consteval void call_for_coprimes_up_to(std::uintmax_t n, const std::array& basis, Callable call) { for (std::uintmax_t i = 0u; i < n; ++i) { if (std::apply([&i](auto... primes) { return ((i % primes != 0) && ...); }, basis)) { @@ -97,7 +97,7 @@ template template [[nodiscard]] consteval auto coprimes_up_to(std::size_t n, const std::array& basis) { - std::array coprimes; + std::array coprimes{}; std::size_t i = 0u; call_for_coprimes_up_to(n, basis, [&coprimes, &i](std::uintmax_t cp) { coprimes[i++] = cp; }); @@ -120,7 +120,7 @@ constexpr std::invoke_result_t> get_fi UnaryFunction f) { for (; first != last; ++first) - if (auto opt = f(*first)) return *opt; + if (auto opt = f(*first)) return opt; return {}; } diff --git a/src/core/include/mp-units/ext/type_name.h b/src/core/include/mp-units/ext/type_name.h index 6cfcca25..e768755e 100644 --- a/src/core/include/mp-units/ext/type_name.h +++ b/src/core/include/mp-units/ext/type_name.h @@ -36,6 +36,7 @@ template template [[nodiscard]] consteval auto better_type_name(T1 v1, T2 v2) { + // NOLINTBEGIN(bugprone-branch-clone) if constexpr (type_name().size() < type_name().size()) return v1; else if constexpr (type_name().size() < type_name().size()) @@ -44,6 +45,7 @@ template return v1; else return v2; + // NOLINTEND(bugprone-branch-clone) } } // namespace mp_units::detail diff --git a/src/core/include/mp-units/format.h b/src/core/include/mp-units/format.h index ccb237c7..d5a3c291 100644 --- a/src/core/include/mp-units/format.h +++ b/src/core/include/mp-units/format.h @@ -44,7 +44,7 @@ struct fill_align_width_format_specs { template [[nodiscard]] constexpr const Char* at_most_one_of(const Char* begin, const Char* end, std::string_view modifiers) { - auto it = find_first_of(begin, end, modifiers.begin(), modifiers.end()); + const Char* const it = find_first_of(begin, end, modifiers.begin(), modifiers.end()); if (it != end && find_first_of(it + 1, end, modifiers.begin(), modifiers.end()) != end) throw MP_UNITS_STD_FMT::format_error("only one of '" + std::string(modifiers) + "' unit modifiers may be used in the format spec"); @@ -141,17 +141,16 @@ public: auto specs = specs_; mp_units::detail::handle_dynamic_spec(specs.width, specs.width_ref, ctx); - if (specs.width == 0) { + if (specs.width == 0) // Avoid extra copying if width is not specified return mp_units::dimension_symbol_to(ctx.out(), d, specs); - } else { - std::basic_string unit_buffer; - mp_units::dimension_symbol_to(std::back_inserter(unit_buffer), d, specs); + std::basic_string unit_buffer; + mp_units::dimension_symbol_to(std::back_inserter(unit_buffer), d, specs); - std::basic_string global_format_buffer = "{:" + std::basic_string{fill_align_width_format_str_} + "}"; - return MP_UNITS_STD_FMT::vformat_to(ctx.out(), global_format_buffer, - MP_UNITS_STD_FMT::make_format_args(unit_buffer)); - } + const std::basic_string global_format_buffer = + "{:" + std::basic_string{fill_align_width_format_str_} + "}"; + return MP_UNITS_STD_FMT::vformat_to(ctx.out(), global_format_buffer, + MP_UNITS_STD_FMT::make_format_args(unit_buffer)); } }; @@ -231,17 +230,16 @@ public: auto specs = specs_; mp_units::detail::handle_dynamic_spec(specs.width, specs.width_ref, ctx); - if (specs.width == 0) { + if (specs.width == 0) // Avoid extra copying if width is not specified return mp_units::unit_symbol_to(ctx.out(), u, specs); - } else { - std::basic_string unit_buffer; - mp_units::unit_symbol_to(std::back_inserter(unit_buffer), u, specs); + std::basic_string unit_buffer; + mp_units::unit_symbol_to(std::back_inserter(unit_buffer), u, specs); - std::basic_string global_format_buffer = "{:" + std::basic_string{fill_align_width_format_str_} + "}"; - return MP_UNITS_STD_FMT::vformat_to(ctx.out(), global_format_buffer, - MP_UNITS_STD_FMT::make_format_args(unit_buffer)); - } + const std::basic_string global_format_buffer = + "{:" + std::basic_string{fill_align_width_format_str_} + "}"; + return MP_UNITS_STD_FMT::vformat_to(ctx.out(), global_format_buffer, + MP_UNITS_STD_FMT::make_format_args(unit_buffer)); } }; @@ -327,7 +325,7 @@ class MP_UNITS_STD_FMT::formatter, Char> { quantity_formatter(const formatter&, OutputIt, Args...) -> quantity_formatter; template - constexpr const Char* parse_quantity_specs(const Char* begin, const Char* end, Handler&& handler) const + constexpr const Char* parse_quantity_specs(const Char* begin, const Char* end, Handler& handler) const { if (begin == end || *begin == ':' || *begin == '}') return begin; if (*begin != '%') @@ -342,9 +340,9 @@ class MP_UNITS_STD_FMT::formatter, Char> { handler.on_text(begin, ++ptr); // account for ':' ++ptr; // consume the second ':' continue; - } else - // default specs started - break; + } + // default specs started + break; } if (c != '%') { ++ptr; @@ -383,9 +381,9 @@ class MP_UNITS_STD_FMT::formatter, Char> { template constexpr const Char* parse_default_spec(const Char* begin, const Char* end, Formatter& f, std::string& format_str) { - if (begin == end || *begin++ != '[') + if (begin == end || *begin != '[') throw MP_UNITS_STD_FMT::format_error("`default-spec` should contain a `[` character"); - auto it = begin; + auto it = ++begin; for (int nested_brackets = 0; it != end && !(*it == ']' && nested_brackets == 0); it++) { if (*it == '[') ++nested_brackets; if (*it == ']') { @@ -428,19 +426,18 @@ class MP_UNITS_STD_FMT::formatter, Char> { template OutputIt format_quantity(OutputIt out, const quantity_t& q, FormatContext& ctx) const { - std::locale locale = MP_UNITS_FMT_LOCALE(ctx.locale()); + const std::locale locale = MP_UNITS_FMT_LOCALE(ctx.locale()); if (modifiers_format_str_.empty()) { // default out = MP_UNITS_STD_FMT::vformat_to(out, locale, rep_format_str_, MP_UNITS_STD_FMT::make_format_args(q.numerical_value_ref_in(q.unit))); if constexpr (mp_units::space_before_unit_symbol) *out++ = ' '; return MP_UNITS_STD_FMT::vformat_to(out, locale, unit_format_str_, MP_UNITS_STD_FMT::make_format_args(q.unit)); - } else { - // user provided format - quantity_formatter f{*this, out, q, locale}; - parse_quantity_specs(modifiers_format_str_.begin(), modifiers_format_str_.end(), f); - return f.out; } + // user provided format + quantity_formatter f{*this, out, q, locale}; + parse_quantity_specs(modifiers_format_str_.begin(), modifiers_format_str_.end(), f); + return f.out; } public: @@ -451,15 +448,15 @@ public: begin = parse_fill_align_width(ctx, begin, end, specs_, mp_units::detail::fmt_align::right); if (begin == end) return begin; - format_checker checker{}; + const format_checker checker{}; auto it = parse_quantity_specs(begin, end, checker); modifiers_format_str_ = {begin, it}; return parse_defaults_specs(it, end); } - template - auto format(const quantity_t& q, FormatContext& ctx) const -> decltype(ctx.out()) + template + OutIt format(const quantity_t& q, MP_UNITS_STD_FMT::basic_format_context& ctx) const { auto specs = specs_; mp_units::detail::handle_dynamic_spec(specs.width, specs.width_ref, ctx); @@ -468,14 +465,13 @@ public: // Avoid extra copying if width is not specified format_quantity(ctx.out(), q, ctx); return ctx.out(); - } else { - std::basic_string quantity_buffer; - format_quantity(std::back_inserter(quantity_buffer), q, ctx); - - std::basic_string fill_align_width_format_str; - mp_units::detail::format_global_buffer(std::back_inserter(fill_align_width_format_str), specs); - return MP_UNITS_STD_FMT::vformat_to(ctx.out(), fill_align_width_format_str, - MP_UNITS_STD_FMT::make_format_args(quantity_buffer)); } + std::basic_string quantity_buffer; + format_quantity(std::back_inserter(quantity_buffer), q, ctx); + + std::basic_string fill_align_width_format_str; + mp_units::detail::format_global_buffer(std::back_inserter(fill_align_width_format_str), specs); + return MP_UNITS_STD_FMT::vformat_to(ctx.out(), fill_align_width_format_str, + MP_UNITS_STD_FMT::make_format_args(quantity_buffer)); } }; diff --git a/src/core/include/mp-units/framework/dimension.h b/src/core/include/mp-units/framework/dimension.h index 55968c4a..770194b9 100644 --- a/src/core/include/mp-units/framework/dimension.h +++ b/src/core/include/mp-units/framework/dimension.h @@ -239,13 +239,13 @@ namespace detail { template Out, Dimension D> requires requires { D::symbol; } -constexpr Out dimension_symbol_impl(Out out, D, dimension_symbol_formatting fmt, bool negative_power) +constexpr Out dimension_symbol_impl(Out out, D, const dimension_symbol_formatting& fmt, bool negative_power) { return copy_symbol(D::symbol, fmt.encoding, negative_power, out); } template Out, typename F, int Num, int... Den> -constexpr auto dimension_symbol_impl(Out out, const power&, dimension_symbol_formatting fmt, +constexpr auto dimension_symbol_impl(Out out, const power&, const dimension_symbol_formatting& fmt, bool negative_power) { out = dimension_symbol_impl(out, F{}, fmt, false); // negative power component will be added below if needed @@ -253,7 +253,7 @@ constexpr auto dimension_symbol_impl(Out out, const power&, dime } template Out, DerivedDimensionExpr... Ms> -constexpr Out dimension_symbol_impl(Out out, const type_list&, dimension_symbol_formatting fmt, +constexpr Out dimension_symbol_impl(Out out, const type_list&, const dimension_symbol_formatting& fmt, bool negative_power) { return (..., (out = dimension_symbol_impl(out, Ms{}, fmt, negative_power))); @@ -261,7 +261,7 @@ constexpr Out dimension_symbol_impl(Out out, const type_list&, dimension_ template Out, DerivedDimensionExpr... Nums, DerivedDimensionExpr... Dens> constexpr Out dimension_symbol_impl(Out out, const type_list& nums, const type_list& dens, - dimension_symbol_formatting fmt) + const dimension_symbol_formatting& fmt) { if constexpr (sizeof...(Nums) == 0 && sizeof...(Dens) == 0) { // dimensionless quantity @@ -277,7 +277,7 @@ constexpr Out dimension_symbol_impl(Out out, const type_list& nums, con } template Out, typename... Expr> -constexpr Out dimension_symbol_impl(Out out, const derived_dimension&, dimension_symbol_formatting fmt, +constexpr Out dimension_symbol_impl(Out out, const derived_dimension&, const dimension_symbol_formatting& fmt, bool negative_power) { gsl_Expects(negative_power == false); @@ -289,7 +289,7 @@ constexpr Out dimension_symbol_impl(Out out, const derived_dimension&, } // namespace detail MP_UNITS_EXPORT template Out, Dimension D> -constexpr Out dimension_symbol_to(Out out, D d, dimension_symbol_formatting fmt = dimension_symbol_formatting{}) +constexpr Out dimension_symbol_to(Out out, D d, const dimension_symbol_formatting& fmt = dimension_symbol_formatting{}) { return detail::dimension_symbol_impl(out, d, fmt, false); } diff --git a/src/core/include/mp-units/framework/magnitude.h b/src/core/include/mp-units/framework/magnitude.h index 29be6d88..1653ad12 100644 --- a/src/core/include/mp-units/framework/magnitude.h +++ b/src/core/include/mp-units/framework/magnitude.h @@ -374,6 +374,7 @@ namespace detail { // Divide a number by a given base raised to some power. // // Undefined unless base > 1, pow >= 0, and (base ^ pow) evenly divides n. +// NOLINTNEXTLINE(bugprone-easily-swappable-parameters) [[nodiscard]] consteval std::intmax_t remove_power(std::intmax_t base, std::intmax_t pow, std::intmax_t n) { while (pow-- > 0) { @@ -795,8 +796,9 @@ template struct prime_factorization { [[nodiscard]] static consteval std::intmax_t get_or_compute_first_factor() { - if constexpr (known_first_factor.has_value()) { - return known_first_factor.value(); + constexpr auto opt = known_first_factor; + if constexpr (opt.has_value()) { + return opt.value(); // NOLINT(bugprone-unchecked-optional-access) } else { return static_cast(factorizer::find_first_factor(N)); } diff --git a/src/core/include/mp-units/framework/quantity.h b/src/core/include/mp-units/framework/quantity.h index e759a86f..3500f0a7 100644 --- a/src/core/include/mp-units/framework/quantity.h +++ b/src/core/include/mp-units/framework/quantity.h @@ -136,6 +136,7 @@ public: quantity() = default; quantity(const quantity&) = default; quantity(quantity&&) = default; + ~quantity() = default; template requires std::same_as, Rep> @@ -227,6 +228,7 @@ public: numerical_value_is_an_implementation_detail_)), convert_explicitly> || !std::convertible_to::rep>) constexpr + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) operator Q_() const& noexcept( noexcept(quantity_like_traits::from_numerical_value(numerical_value_is_an_implementation_detail_)) && std::is_nothrow_copy_constructible_v) @@ -241,6 +243,7 @@ public: numerical_value_is_an_implementation_detail_)), convert_explicitly> || !std::convertible_to::rep>) constexpr + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) operator Q_() && noexcept( noexcept(quantity_like_traits::from_numerical_value(numerical_value_is_an_implementation_detail_)) && std::is_nothrow_move_constructible_v) @@ -529,19 +532,15 @@ MP_UNITS_EXPORT_END } // namespace mp_units -namespace std { - template requires requires { { mp_units::common_reference(Q1::reference, Q2::reference) } -> mp_units::Reference; - typename common_type_t; + typename std::common_type_t; } -struct common_type { +struct std::common_type { public: using type = mp_units::quantity>; + std::common_type_t>; }; - -} // namespace std diff --git a/src/core/include/mp-units/framework/quantity_point.h b/src/core/include/mp-units/framework/quantity_point.h index 5b6699e3..6ad79403 100644 --- a/src/core/include/mp-units/framework/quantity_point.h +++ b/src/core/include/mp-units/framework/quantity_point.h @@ -36,6 +36,7 @@ namespace mp_units { MP_UNITS_EXPORT template +// NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility) struct absolute_point_origin { static constexpr QuantitySpec auto quantity_spec = QS; using _type_ = absolute_point_origin; @@ -157,6 +158,7 @@ public: quantity_point() = default; quantity_point(const quantity_point&) = default; quantity_point(quantity_point&&) = default; + ~quantity_point() = default; template requires QuantityOf, get_quantity_spec(R)> && std::constructible_from && @@ -290,6 +292,7 @@ public: convert_explicitly> || !std::convertible_to::reference, typename quantity_point_like_traits::rep>>) constexpr + // NOLINTNEXTLINE(*-explicit-conversions, google-explicit-constructor) operator QP_() const& noexcept( noexcept(quantity_point_like_traits::from_quantity(quantity_from_origin_is_an_implementation_detail_)) && std::is_nothrow_copy_constructible_v) @@ -307,6 +310,7 @@ public: convert_explicitly> || !std::convertible_to::reference, typename quantity_point_like_traits::rep>>) constexpr + // NOLINTNEXTLINE(*-explicit-conversions, google-explicit-constructor) operator QP_() && noexcept( noexcept(quantity_point_like_traits::from_quantity(quantity_from_origin_is_an_implementation_detail_)) && std::is_nothrow_move_constructible_v) diff --git a/src/core/include/mp-units/framework/quantity_spec.h b/src/core/include/mp-units/framework/quantity_spec.h index bbd4941c..e052a7d6 100644 --- a/src/core/include/mp-units/framework/quantity_spec.h +++ b/src/core/include/mp-units/framework/quantity_spec.h @@ -595,7 +595,7 @@ MP_UNITS_EXPORT_END namespace detail { -enum class specs_convertible_result { no, cast, explicit_conversion, yes }; +enum class specs_convertible_result : std::int8_t { no, cast, explicit_conversion, yes }; template [[nodiscard]] consteval int get_complexity(Q); @@ -634,9 +634,7 @@ template template [[nodiscard]] consteval bool ingredients_dimension_less(D1 lhs, D2 rhs) { - if constexpr (lhs == rhs) - return false; - else if constexpr (lhs == dimension_one) + if constexpr (lhs == rhs || lhs == dimension_one) return false; else if constexpr (rhs == dimension_one) return true; @@ -775,7 +773,7 @@ template template [[nodiscard]] consteval auto explode(Q, type_list<>, type_list<>) { - return explode_result{dimensionless}; + return explode_result{.quantity = dimensionless}; } template @@ -868,11 +866,11 @@ template [[nodiscard]] consteval specs_convertible_result are_ingredients_convertible(type_list<>, type_list<>, type_list<>, type_list<>); -enum class prepend_rest { no, first, second }; +enum class prepend_rest : std::int8_t { no, first, second }; template struct extract_results { - bool same_dimension; + bool same_dimension{}; From from{}; To to{}; prepend_rest prepend{}; @@ -914,7 +912,7 @@ template constexpr auto to_factor = std::get<0>(to_norm); constexpr auto to_exp = std::get<1>(to_norm); if constexpr (from_factor.dimension != to_factor.dimension) - return extract_results{false}; + return extract_results{.same_dimension = false}; else if constexpr (from_exp > to_exp) return extract_results{true, pow(from_factor), pow(to_factor), prepend_rest::first, @@ -926,30 +924,37 @@ template } } -enum class process_entities { numerators, denominators, from, to }; +enum class process_entities : std::int8_t { numerators, denominators, from, to }; + +template +[[nodiscard]] consteval specs_convertible_result process_num_den(NumFrom num_from, DenFrom den_from, NumTo num_to, + DenTo den_to) +{ + constexpr auto res = convertible_impl(Ext.from, Ext.to); + if constexpr (Ext.prepend == prepend_rest::no) + return min(res, are_ingredients_convertible(num_from, den_from, num_to, den_to)); + else { + using elem = std::remove_cvref_t; + if constexpr (Entities == process_entities::numerators) { + if constexpr (Ext.prepend == prepend_rest::first) + return min(res, are_ingredients_convertible(type_list_push_front{}, den_from, num_to, den_to)); + else + return min(res, are_ingredients_convertible(num_from, den_from, type_list_push_front{}, den_to)); + } else { + if constexpr (Ext.prepend == prepend_rest::first) + return min(res, are_ingredients_convertible(num_from, type_list_push_front{}, num_to, den_to)); + else + return min(res, are_ingredients_convertible(num_from, den_from, num_to, type_list_push_front{})); + } + } +} template [[nodiscard]] consteval specs_convertible_result process_extracted(NumFrom num_from, DenFrom den_from, NumTo num_to, DenTo den_to) { if constexpr (Entities == process_entities::numerators || Entities == process_entities::denominators) { - constexpr auto res = convertible_impl(Ext.from, Ext.to); - if constexpr (Ext.prepend == prepend_rest::no) - return min(res, are_ingredients_convertible(num_from, den_from, num_to, den_to)); - else { - using elem = std::remove_cvref_t; - if constexpr (Entities == process_entities::numerators) { - if constexpr (Ext.prepend == prepend_rest::first) - return min(res, are_ingredients_convertible(type_list_push_front{}, den_from, num_to, den_to)); - else - return min(res, are_ingredients_convertible(num_from, den_from, type_list_push_front{}, den_to)); - } else { - if constexpr (Ext.prepend == prepend_rest::first) - return min(res, are_ingredients_convertible(num_from, type_list_push_front{}, num_to, den_to)); - else - return min(res, are_ingredients_convertible(num_from, den_from, num_to, type_list_push_front{})); - } - } + return process_num_den(num_from, den_from, num_to, den_to); } else { if constexpr (Ext.prepend == prepend_rest::no) return are_ingredients_convertible(num_from, den_from, num_to, den_to); @@ -1330,50 +1335,63 @@ template type_list_sort{}); } +template +[[nodiscard]] consteval specs_convertible_result convertible_kinds(From from_kind, To to_kind) +{ + constexpr auto exploded_kind_result = [](specs_convertible_result res) { + using enum specs_convertible_result; + return res == no ? no : yes; + }; + if constexpr ((NamedQuantitySpec> && + NamedQuantitySpec>) || + get_complexity(from_kind) == get_complexity(to_kind)) + return convertible_impl(from_kind, to_kind); + else if constexpr (get_complexity(from_kind) > get_complexity(to_kind)) + return exploded_kind_result( + convertible_impl(get_kind_tree_root(explode(from_kind).quantity), to_kind)); + else + return exploded_kind_result( + convertible_impl(from_kind, get_kind_tree_root(explode(to_kind).quantity))); +} + +template +[[nodiscard]] consteval specs_convertible_result convertible_named(From from, To to) +{ + using enum specs_convertible_result; + + if constexpr (have_common_base(From{}, To{})) { + if constexpr (std::derived_from) return yes; + if constexpr (std::derived_from) return explicit_conversion; + if constexpr (get_kind(From{}) == get_kind(To{})) return cast; + return no; + } else if constexpr (get_kind(From{}) != get_kind(To{})) + return no; + else if constexpr (get_complexity(From{}) != get_complexity(To{})) { + if constexpr (get_complexity(From{}) > get_complexity(To{})) + return convertible_impl(explode(from).quantity, to); + else { + auto res = explode(to); + return min(res.result, convertible_impl(from, res.quantity)); + } + } +} + template [[nodiscard]] consteval specs_convertible_result convertible_impl(From from, To to) { using enum specs_convertible_result; + // NOLINTBEGIN(bugprone-branch-clone) if constexpr (From::dimension != To::dimension) return no; else if constexpr (From{} == To{}) return yes; else if constexpr (QuantityKindSpec || QuantityKindSpec) { - constexpr auto from_kind = get_kind_tree_root(From{}); - constexpr auto to_kind = get_kind_tree_root(To{}); - constexpr auto exploded_kind_result = [](specs_convertible_result res) { - using enum specs_convertible_result; - return res == no ? no : yes; - }; - if constexpr ((NamedQuantitySpec> && - NamedQuantitySpec>) || - get_complexity(from_kind) == get_complexity(to_kind)) - return convertible_impl(from_kind, to_kind); - else if constexpr (get_complexity(from_kind) > get_complexity(to_kind)) - return exploded_kind_result( - convertible_impl(get_kind_tree_root(explode(from_kind).quantity), to_kind)); - else - return exploded_kind_result( - convertible_impl(from_kind, get_kind_tree_root(explode(to_kind).quantity))); + return convertible_kinds(get_kind_tree_root(from), get_kind_tree_root(to)); } else if constexpr (NestedQuantityKindSpecOf && get_kind_tree_root(To{}) == To{}) return yes; else if constexpr (NamedQuantitySpec && NamedQuantitySpec) { - if constexpr (have_common_base(From{}, To{})) { - if (std::derived_from) - return yes; - else - return std::derived_from ? explicit_conversion : (get_kind(from) == get_kind(to) ? cast : no); - } else if constexpr (get_kind(From{}) != get_kind(To{})) - return no; - else if constexpr (get_complexity(From{}) != get_complexity(To{})) { - if constexpr (get_complexity(From{}) > get_complexity(To{})) - return convertible_impl(explode(from).quantity, to); - else { - auto res = explode(to); - return min(res.result, convertible_impl(from, res.quantity)); - } - } + return convertible_named(from, to); } else if constexpr (IntermediateDerivedQuantitySpec && IntermediateDerivedQuantitySpec) { return are_ingredients_convertible(from, to); } else if constexpr (IntermediateDerivedQuantitySpec) { @@ -1394,6 +1412,7 @@ template else return min(res.result, are_ingredients_convertible(from, to)); } + // NOLINTEND(bugprone-branch-clone) return no; } @@ -1454,6 +1473,7 @@ template return false; }; + // NOLINTBEGIN(bugprone-branch-clone) if constexpr (detail::QuantityKindSpec) { return remove_kind(q); } else if constexpr (defined_as_kind(Q{})) { @@ -1467,6 +1487,7 @@ template // root quantity return q; } + // NOLINTEND(bugprone-branch-clone) } } // namespace detail @@ -1488,6 +1509,8 @@ template { using QQ1 = std::remove_const_t; using QQ2 = std::remove_const_t; + + // NOLINTBEGIN(bugprone-branch-clone) if constexpr (is_same_v) return q1; else if constexpr (detail::NestedQuantityKindSpecOf) @@ -1512,6 +1535,7 @@ template return get_kind_tree_root(q2); else return get_kind_tree_root(q1); + // NOLINTEND(bugprone-branch-clone) } [[nodiscard]] consteval QuantitySpec auto common_quantity_spec(QuantitySpec auto q1, QuantitySpec auto q2, diff --git a/src/core/include/mp-units/framework/representation_concepts.h b/src/core/include/mp-units/framework/representation_concepts.h index 7c7be67e..74014074 100644 --- a/src/core/include/mp-units/framework/representation_concepts.h +++ b/src/core/include/mp-units/framework/representation_concepts.h @@ -53,7 +53,7 @@ namespace mp_units { * For example, the Cauchy stress tensor possess magnitude, direction, * and orientation qualities. */ -MP_UNITS_EXPORT enum class quantity_character { scalar, vector, tensor }; +MP_UNITS_EXPORT enum class quantity_character : std::int8_t { scalar, vector, tensor }; namespace detail { diff --git a/src/core/include/mp-units/framework/symbol_text.h b/src/core/include/mp-units/framework/symbol_text.h index b70b3d2f..f64e2d5b 100644 --- a/src/core/include/mp-units/framework/symbol_text.h +++ b/src/core/include/mp-units/framework/symbol_text.h @@ -20,6 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +// NOLINTBEGIN(*-avoid-c-arrays) #pragma once // IWYU pragma: private, include @@ -43,6 +44,7 @@ static_assert(std::text_encoding::literal().mib() == std::text_encoding::id::UTF namespace mp_units { +// NOLINTNEXTLINE(readability-enum-initial-value) MP_UNITS_EXPORT enum class text_encoding : std::int8_t { unicode, // µs; m³; L²MT⁻³ ascii, // us; m^3; L^2MT^-3 @@ -60,9 +62,7 @@ constexpr bool is_basic_literal_character_set_char(char ch) template constexpr bool is_basic_literal_character_set(const char (&txt)[N]) noexcept { - for (auto ch : txt) - if (!is_basic_literal_character_set_char(ch)) return false; - return true; + return detail::all_of(std::begin(txt), std::end(txt), is_basic_literal_character_set_char); } template @@ -94,6 +94,7 @@ struct symbol_text { gsl_Expects(detail::is_basic_literal_character_set_char(ch)); } + // NOLINTNEXTLINE(*-avoid-c-arrays) constexpr explicit(false) symbol_text(const char (&txt)[N + 1]) : unicode_(detail::to_u8string(basic_fixed_string{txt})), ascii_(txt) { @@ -106,6 +107,7 @@ struct symbol_text { gsl_Expects(detail::is_basic_literal_character_set(txt.data_)); } + // NOLINTNEXTLINE(*-avoid-c-arrays) constexpr symbol_text(const char8_t (&u)[N + 1], const char (&a)[M + 1]) : unicode_(u), ascii_(a) { gsl_Expects(u[N] == char8_t{}); @@ -166,3 +168,4 @@ template symbol_text(const fixed_u8string&, const fixed_string&) -> symbol_text; } // namespace mp_units +// NOLINTEND(*-avoid-c-arrays) diff --git a/src/core/include/mp-units/framework/unit.h b/src/core/include/mp-units/framework/unit.h index 16d89822..0c3b7aa6 100644 --- a/src/core/include/mp-units/framework/unit.h +++ b/src/core/include/mp-units/framework/unit.h @@ -688,6 +688,7 @@ inline constexpr bool space_before_unit_symbol = false; // get_unit_symbol +// NOLINTNEXTLINE(readability-enum-initial-value) enum class unit_symbol_solidus : std::int8_t { one_denominator, // m/s; kg m⁻¹ s⁻¹ always, // m/s; kg/(m s) @@ -695,6 +696,7 @@ enum class unit_symbol_solidus : std::int8_t { default_denominator = one_denominator }; +// NOLINTNEXTLINE(readability-enum-initial-value) enum class unit_symbol_separator : std::int8_t { space, // kg m²/s² half_high_dot, // kg⋅m²/s² (valid only for unicode encoding) @@ -712,7 +714,7 @@ MP_UNITS_EXPORT_END namespace detail { template Out> -constexpr Out print_separator(Out out, unit_symbol_formatting fmt) +constexpr Out print_separator(Out out, const unit_symbol_formatting& fmt) { if (fmt.separator == unit_symbol_separator::half_high_dot) { if (fmt.encoding != text_encoding::unicode) @@ -727,13 +729,14 @@ constexpr Out print_separator(Out out, unit_symbol_formatting fmt) template Out, Unit U> requires requires { U::symbol; } -constexpr Out unit_symbol_impl(Out out, U, unit_symbol_formatting fmt, bool negative_power) +constexpr Out unit_symbol_impl(Out out, U, const unit_symbol_formatting& fmt, bool negative_power) { return copy_symbol(U::symbol, fmt.encoding, negative_power, out); } template Out, auto M, typename U> -constexpr Out unit_symbol_impl(Out out, const scaled_unit& u, unit_symbol_formatting fmt, bool negative_power) +constexpr Out unit_symbol_impl(Out out, const scaled_unit& u, const unit_symbol_formatting& fmt, + bool negative_power) { if constexpr (M == mag<1>) { // no ratio/prefix @@ -748,14 +751,15 @@ constexpr Out unit_symbol_impl(Out out, const scaled_unit& u, unit_symbol_ } template Out, typename F, int Num, int... Den> -constexpr auto unit_symbol_impl(Out out, const power&, unit_symbol_formatting fmt, bool negative_power) +constexpr auto unit_symbol_impl(Out out, const power&, const unit_symbol_formatting& fmt, + bool negative_power) { out = unit_symbol_impl(out, F{}, fmt, false); // negative power component will be added below if needed return copy_symbol_exponent(fmt.encoding, negative_power, out); } template Out, DerivedUnitExpr M> -constexpr Out unit_symbol_impl(Out out, M m, std::size_t Idx, unit_symbol_formatting fmt, bool negative_power) +constexpr Out unit_symbol_impl(Out out, M m, std::size_t Idx, const unit_symbol_formatting& fmt, bool negative_power) { if (Idx > 0) out = print_separator(out, fmt); return unit_symbol_impl(out, m, fmt, negative_power); @@ -763,14 +767,14 @@ constexpr Out unit_symbol_impl(Out out, M m, std::size_t Idx, unit_symbol_format template Out, DerivedUnitExpr... Ms, std::size_t... Idxs> constexpr Out unit_symbol_impl(Out out, const type_list&, std::index_sequence, - unit_symbol_formatting fmt, bool negative_power) + const unit_symbol_formatting& fmt, bool negative_power) { return (..., (out = unit_symbol_impl(out, Ms{}, Idxs, fmt, negative_power))); } template Out, DerivedUnitExpr... Nums, DerivedUnitExpr... Dens> constexpr Out unit_symbol_impl(Out out, const type_list& nums, const type_list& dens, - unit_symbol_formatting fmt) + const unit_symbol_formatting& fmt) { if constexpr (sizeof...(Nums) == 0 && sizeof...(Dens) == 0) { // dimensionless quantity @@ -792,7 +796,7 @@ constexpr Out unit_symbol_impl(Out out, const type_list& nums, const ty } if (fmt.solidus == always && sizeof...(Dens) > 1) *out++ = '('; - bool negative_power = fmt.solidus == never || (fmt.solidus == one_denominator && sizeof...(Dens) > 1); + const bool negative_power = fmt.solidus == never || (fmt.solidus == one_denominator && sizeof...(Dens) > 1); out = unit_symbol_impl(out, dens, std::index_sequence_for(), fmt, negative_power); if (fmt.solidus == always && sizeof...(Dens) > 1) *out++ = ')'; return out; @@ -800,7 +804,8 @@ constexpr Out unit_symbol_impl(Out out, const type_list& nums, const ty } template Out, typename... Expr> -constexpr Out unit_symbol_impl(Out out, const derived_unit&, unit_symbol_formatting fmt, bool negative_power) +constexpr Out unit_symbol_impl(Out out, const derived_unit&, const unit_symbol_formatting& fmt, + bool negative_power) { gsl_Expects(negative_power == false); return unit_symbol_impl(out, typename derived_unit::_num_{}, typename derived_unit::_den_{}, @@ -810,7 +815,7 @@ constexpr Out unit_symbol_impl(Out out, const derived_unit&, unit_symbo } // namespace detail MP_UNITS_EXPORT template Out, Unit U> -constexpr Out unit_symbol_to(Out out, U u, unit_symbol_formatting fmt = unit_symbol_formatting{}) +constexpr Out unit_symbol_to(Out out, U u, const unit_symbol_formatting& fmt = unit_symbol_formatting{}) { return detail::unit_symbol_impl(out, u, fmt, false); } diff --git a/src/core/include/mp-units/random.h b/src/core/include/mp-units/random.h index aa097e80..5736451d 100644 --- a/src/core/include/mp-units/random.h +++ b/src/core/include/mp-units/random.h @@ -39,7 +39,7 @@ std::vector i_qty_to_rep(InputIt first, InputIt last) { std::vector intervals_rep; intervals_rep.reserve(static_cast(std::distance(first, last))); - for (auto itr = first; itr != last; ++itr) { + for (InputIt itr = first; itr != last; ++itr) { intervals_rep.push_back(itr->numerical_value_ref_in(Q::unit)); } return intervals_rep; @@ -106,11 +106,11 @@ struct uniform_int_distribution : public std::uniform_int_distribution @@ -131,11 +131,11 @@ struct uniform_real_distribution : public std::uniform_real_distribution @@ -153,10 +153,10 @@ struct binomial_distribution : public std::binomial_distribution @@ -174,10 +174,10 @@ struct negative_binomial_distribution : public std::negative_binomial_distributi return base::operator()(g) * Q::reference; } - Q k() const { return base::k() * Q::reference; } + [[nodiscard]] Q k() const { return base::k() * Q::reference; } - Q min() const { return base::min() * Q::reference; } - Q max() const { return base::max() * Q::reference; } + [[nodiscard]] Q min() const { return base::min() * Q::reference; } + [[nodiscard]] Q max() const { return base::max() * Q::reference; } }; template @@ -187,7 +187,7 @@ struct geometric_distribution : public std::geometric_distribution; geometric_distribution() : base() {} - geometric_distribution(double p) : base(p) {} + explicit geometric_distribution(double p) : base(p) {} template Q operator()(Generator& g) @@ -195,8 +195,8 @@ struct geometric_distribution : public std::geometric_distribution @@ -214,8 +214,8 @@ struct poisson_distribution : public std::poisson_distribution return base::operator()(g) * Q::reference; } - Q min() const { return base::min() * Q::reference; } - Q max() const { return base::max() * Q::reference; } + [[nodiscard]] Q min() const { return base::min() * Q::reference; } + [[nodiscard]] Q max() const { return base::max() * Q::reference; } }; template @@ -233,8 +233,8 @@ struct exponential_distribution : public std::exponential_distribution @@ -252,8 +252,8 @@ struct gamma_distribution : public std::gamma_distribution { return base::operator()(g) * Q::reference; } - Q min() const { return base::min() * Q::reference; } - Q max() const { return base::max() * Q::reference; } + [[nodiscard]] Q min() const { return base::min() * Q::reference; } + [[nodiscard]] Q max() const { return base::max() * Q::reference; } }; template @@ -271,8 +271,8 @@ struct weibull_distribution : public std::weibull_distribution return base::operator()(g) * Q::reference; } - Q min() const { return base::min() * Q::reference; } - Q max() const { return base::max() * Q::reference; } + [[nodiscard]] Q min() const { return base::min() * Q::reference; } + [[nodiscard]] Q max() const { return base::max() * Q::reference; } }; template @@ -290,10 +290,10 @@ struct extreme_value_distribution : public std::extreme_value_distribution @@ -314,11 +314,11 @@ struct normal_distribution : public std::normal_distribution { return Q(base::operator()(g)); } - Q mean() const { return base::mean() * Q::reference; } - Q stddev() const { return base::stddev() * Q::reference; } + [[nodiscard]] Q mean() const { return base::mean() * Q::reference; } + [[nodiscard]] Q stddev() const { return base::stddev() * Q::reference; } - Q min() const { return base::min() * Q::reference; } - Q max() const { return base::max() * Q::reference; } + [[nodiscard]] Q min() const { return base::min() * Q::reference; } + [[nodiscard]] Q max() const { return base::max() * Q::reference; } }; template @@ -339,11 +339,11 @@ struct lognormal_distribution : public std::lognormal_distribution @@ -361,8 +361,8 @@ struct chi_squared_distribution : public std::chi_squared_distribution @@ -383,11 +383,11 @@ struct cauchy_distribution : public std::cauchy_distribution { return base::operator()(g) * Q::reference; } - Q a() const { return base::a() * Q::reference; } - Q b() const { return base::b() * Q::reference; } + [[nodiscard]] Q a() const { return base::a() * Q::reference; } + [[nodiscard]] Q b() const { return base::b() * Q::reference; } - Q min() const { return base::min() * Q::reference; } - Q max() const { return base::max() * Q::reference; } + [[nodiscard]] Q min() const { return base::min() * Q::reference; } + [[nodiscard]] Q max() const { return base::max() * Q::reference; } }; template @@ -405,8 +405,8 @@ struct fisher_f_distribution : public std::fisher_f_distribution @@ -424,8 +424,8 @@ struct student_t_distribution : public std::student_t_distribution @@ -455,8 +455,8 @@ struct discrete_distribution : public std::discrete_distribution @@ -503,9 +503,9 @@ public: return base::operator()(g) * Q::reference; } - std::vector intervals() const + [[nodiscard]] std::vector intervals() const { - std::vector intervals_rep = base::intervals(); + const std::vector intervals_rep = base::intervals(); std::vector intervals_qty; intervals_qty.reserve(intervals_rep.size()); for (const rep& val : intervals_rep) { @@ -514,8 +514,8 @@ public: return intervals_qty; } - Q min() const { return base::min() * Q::reference; } - Q max() const { return base::max() * Q::reference; } + [[nodiscard]] Q min() const { return base::min() * Q::reference; } + [[nodiscard]] Q max() const { return base::max() * Q::reference; } }; template @@ -562,9 +562,9 @@ public: return base::operator()(g) * Q::reference; } - std::vector intervals() const + [[nodiscard]] std::vector intervals() const { - std::vector intervals_rep = base::intervals(); + const std::vector intervals_rep = base::intervals(); std::vector intervals_qty; intervals_qty.reserve(intervals_rep.size()); for (const rep& val : intervals_rep) { @@ -573,8 +573,8 @@ public: return intervals_qty; } - Q min() const { return base::min() * Q::reference; } - Q max() const { return base::max() * Q::reference; } + [[nodiscard]] Q min() const { return base::min() * Q::reference; } + [[nodiscard]] Q max() const { return base::max() * Q::reference; } }; MP_UNITS_EXPORT_END diff --git a/src/systems/include/mp-units/systems/iau.h b/src/systems/include/mp-units/systems/iau.h index abbe963d..8d4aeaa8 100644 --- a/src/systems/include/mp-units/systems/iau.h +++ b/src/systems/include/mp-units/systems/iau.h @@ -59,7 +59,7 @@ inline constexpr struct lunar_distance : named_unit<"LD", mag<384'399> * si::kil inline constexpr struct light_year : named_unit<"ly", mag<9'460'730'472'580'800> * si::metre> {} light_year; // https://en.wikipedia.org/wiki/Parsec -inline constexpr struct parsec : named_unit<"pc", astronomical_unit / (mag_ratio<1, 60 * 60> * si::degree)> {} parsec; +inline constexpr struct parsec : named_unit<"pc", astronomical_unit / (mag_ratio<1, 3600> * si::degree)> {} parsec; // https://en.wikipedia.org/wiki/Angstrom inline constexpr struct angstrom : named_unit * si::metre> {} angstrom; diff --git a/src/systems/include/mp-units/systems/si/chrono.h b/src/systems/include/mp-units/systems/si/chrono.h index b8bcc589..e0e5422d 100644 --- a/src/systems/include/mp-units/systems/si/chrono.h +++ b/src/systems/include/mp-units/systems/si/chrono.h @@ -38,7 +38,7 @@ namespace mp_units { namespace detail { template -[[nodiscard]] inline consteval auto time_unit_from_chrono_period() +[[nodiscard]] consteval auto time_unit_from_chrono_period() { using namespace si; diff --git a/src/systems/include/mp-units/systems/si/unit_symbols.h b/src/systems/include/mp-units/systems/si/unit_symbols.h index fe28311f..8477bbb2 100644 --- a/src/systems/include/mp-units/systems/si/unit_symbols.h +++ b/src/systems/include/mp-units/systems/si/unit_symbols.h @@ -769,7 +769,7 @@ inline constexpr auto d = day; namespace si::unit_symbols { -using namespace non_si::unit_symbols; +using namespace non_si::unit_symbols; // NOLINT(google-build-using-namespace) } // namespace si::unit_symbols diff --git a/test/.clang-tidy b/test/.clang-tidy new file mode 100644 index 00000000..7919114d --- /dev/null +++ b/test/.clang-tidy @@ -0,0 +1,7 @@ +Checks: ' + -bugprone-chained-comparison, + -cppcoreguidelines-avoid-magic-numbers, + -google-build-using-namespace, + -readability-function-cognitive-complexity +' +InheritParentConfig: true diff --git a/test/runtime/almost_equals.h b/test/runtime/almost_equals.h index 9a6f3bfd..22de4a18 100644 --- a/test/runtime/almost_equals.h +++ b/test/runtime/almost_equals.h @@ -34,7 +34,7 @@ namespace mp_units { template struct AlmostEqualsMatcher : Catch::Matchers::MatcherGenericBase { - AlmostEqualsMatcher(const T& target) : target_{target} {} + explicit AlmostEqualsMatcher(const T& target) : target_{target} {} template U> requires std::same_as && treat_as_floating_point @@ -57,7 +57,7 @@ private: template AlmostEqualsMatcher AlmostEquals(const T& target) { - return {target}; + return AlmostEqualsMatcher{target}; } } // namespace mp_units diff --git a/test/runtime/atomic_test.cpp b/test/runtime/atomic_test.cpp index f5ca138d..64e00915 100644 --- a/test/runtime/atomic_test.cpp +++ b/test/runtime/atomic_test.cpp @@ -35,7 +35,7 @@ using namespace mp_units::si::unit_symbols; TEST_CASE("std::atomic works with dimensioned types", "[atomic][assignment]") { - std::atomic> a1 = 3.0 * isq::area[m2]; - std::atomic> a2 = 3.0 * isq::area[m2]; + const std::atomic> a1 = 3.0 * isq::area[m2]; + const std::atomic> a2 = 3.0 * isq::area[m2]; REQUIRE(a1.load() == a2.load()); } diff --git a/test/runtime/distribution_test.cpp b/test/runtime/distribution_test.cpp index dc2a7137..ce7cb6b8 100644 --- a/test/runtime/distribution_test.cpp +++ b/test/runtime/distribution_test.cpp @@ -499,7 +499,7 @@ TEST_CASE("discrete_distribution") SECTION("parametrized_initializer_list") { - std::initializer_list weights = {1.0, 2.0, 3.0}; + const std::initializer_list weights = {1.0, 2.0, 3.0}; auto stl_dist = std::discrete_distribution(weights); auto units_dist = mp_units::discrete_distribution(weights); @@ -560,8 +560,8 @@ TEST_CASE("piecewise_constant_distribution") SECTION("parametrized_initializer_list") { - std::initializer_list intervals_rep = {1.0, 2.0, 3.0}; - std::initializer_list intervals_qty = {1.0 * isq::length[si::metre], 2.0 * isq::length[si::metre], + const std::initializer_list intervals_rep = {1.0, 2.0, 3.0}; + const std::initializer_list intervals_qty = {1.0 * isq::length[si::metre], 2.0 * isq::length[si::metre], 3.0 * isq::length[si::metre]}; auto stl_dist = std::piecewise_constant_distribution(intervals_rep, [](rep val) { return val; }); @@ -628,8 +628,8 @@ TEST_CASE("piecewise_linear_distribution") SECTION("parametrized_initializer_list") { - std::initializer_list intervals_rep = {1.0, 2.0, 3.0}; - std::initializer_list intervals_qty = {1.0 * isq::length[si::metre], 2.0 * isq::length[si::metre], + const std::initializer_list intervals_rep = {1.0, 2.0, 3.0}; + const std::initializer_list intervals_qty = {1.0 * isq::length[si::metre], 2.0 * isq::length[si::metre], 3.0 * isq::length[si::metre]}; auto stl_dist = std::piecewise_linear_distribution(intervals_rep, [](rep val) { return val; }); diff --git a/test/runtime/fmt_test.cpp b/test/runtime/fmt_test.cpp index 13f7e461..e8437438 100644 --- a/test/runtime/fmt_test.cpp +++ b/test/runtime/fmt_test.cpp @@ -999,17 +999,17 @@ TEST_CASE("different base types with the # specifier", "[text][fmt]") TEST_CASE("localization with the 'L' specifier", "[text][fmt][localization]") { struct group2 : std::numpunct { - char do_thousands_sep() const override { return '_'; } - std::string do_grouping() const override { return "\2"; } + [[nodiscard]] char do_thousands_sep() const override { return '_'; } + [[nodiscard]] std::string do_grouping() const override { return "\2"; } }; struct group3 : std::numpunct { - char do_thousands_sep() const override { return '\''; } - std::string do_grouping() const override { return "\3"; } + [[nodiscard]] char do_thousands_sep() const override { return '\''; } + [[nodiscard]] std::string do_grouping() const override { return "\3"; } }; - std::locale grp2{std::locale::classic(), new group2}; - std::locale grp3{std::locale::classic(), new group3}; + const std::locale grp2{std::locale::classic(), new group2}; + const std::locale grp3{std::locale::classic(), new group3}; SECTION("full format on a quantity") { diff --git a/test/static/custom_rep_test_min_impl.cpp b/test/static/custom_rep_test_min_impl.cpp index 75e63330..4b8465e9 100644 --- a/test/static/custom_rep_test_min_impl.cpp +++ b/test/static/custom_rep_test_min_impl.cpp @@ -48,6 +48,7 @@ public: constexpr explicit(false) min_impl(min_impl i) noexcept : value_(static_cast(static_cast(i))) { } + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) constexpr explicit(false) operator T() const noexcept { return value_; } }; @@ -140,9 +141,9 @@ static_assert(min_impl{1} * si::metre + min_impl{1.5} * si::metre = static_assert(1 * si::metre + min_impl{1} * si::metre == min_impl{2} * si::metre); static_assert(1 * si::metre + min_impl{1.5} * si::metre == min_impl{2.5} * si::metre); static_assert(min_impl{1} * si::metre + 1 * si::metre == min_impl{2} * si::metre); -static_assert(min_impl{1} * si::metre + double{1.5} * si::metre == min_impl{2.5} * si::metre); +static_assert(min_impl{1} * si::metre + 1.5 * si::metre == min_impl{2.5} * si::metre); static_assert(min_impl{1} * si::metre + min_impl{1} * si::metre == 2 * si::metre); -static_assert(min_impl{1} * si::metre + min_impl{1.5} * si::metre == double{2.5} * si::metre); +static_assert(min_impl{1} * si::metre + min_impl{1.5} * si::metre == 2.5 * si::metre); static_assert(min_impl{1} * si::kilo + min_impl{1} * si::metre == min_impl{1'001} * si::metre); @@ -151,9 +152,9 @@ static_assert(min_impl{1} * si::kilo + min_impl{1.5} * s static_assert(1 * si::kilo + min_impl{1} * si::metre == min_impl{1'001} * si::metre); static_assert(1 * si::kilo + min_impl{1.5} * si::metre == min_impl{1001.5} * si::metre); static_assert(min_impl{1} * si::kilo + 1 * si::metre == min_impl{1'001} * si::metre); -static_assert(min_impl{1} * si::kilo + double{1.5} * si::metre == min_impl{1001.5} * si::metre); +static_assert(min_impl{1} * si::kilo + 1.5 * si::metre == min_impl{1001.5} * si::metre); static_assert(min_impl{1} * si::kilo + min_impl{1} * si::metre == 1'001 * si::metre); -static_assert(min_impl{1} * si::kilo + min_impl{1.5} * si::metre == double{1001.5} * si::metre); +static_assert(min_impl{1} * si::kilo + min_impl{1.5} * si::metre == 1001.5 * si::metre); static_assert(min_impl{1} * si::metre + min_impl{1} * si::kilo == min_impl{1'001} * si::metre); @@ -162,7 +163,7 @@ static_assert(min_impl{1} * si::metre + min_impl{1.5} * si::kilo{1} * si::kilo == min_impl{1'001} * si::metre); static_assert(1 * si::metre + min_impl{1.5} * si::kilo == min_impl{1'501} * si::metre); static_assert(min_impl{1} * si::metre + 1 * si::kilo == min_impl{1'001} * si::metre); -static_assert(min_impl{1} * si::metre + double{1.5} * si::kilo == min_impl{1'501} * si::metre); +static_assert(min_impl{1} * si::metre + 1.5 * si::kilo == min_impl{1'501} * si::metre); static_assert(min_impl{1} * si::metre + min_impl{1} * si::kilo == 1'001 * si::metre); static_assert(min_impl{1} * si::metre + min_impl{1.5} * si::kilo == double{1'501} * si::metre); @@ -171,9 +172,9 @@ static_assert(min_impl{2} * si::metre - min_impl{1.5} * si::metre = static_assert(2 * si::metre - min_impl{1} * si::metre == min_impl{1} * si::metre); static_assert(2 * si::metre - min_impl{1.5} * si::metre == min_impl{0.5} * si::metre); static_assert(min_impl{2} * si::metre - 1 * si::metre == min_impl{1} * si::metre); -static_assert(min_impl{2} * si::metre - double{1.5} * si::metre == min_impl{0.5} * si::metre); +static_assert(min_impl{2} * si::metre - 1.5 * si::metre == min_impl{0.5} * si::metre); static_assert(min_impl{2} * si::metre - min_impl{1} * si::metre == 1 * si::metre); -static_assert(min_impl{2} * si::metre - min_impl{1.5} * si::metre == double{0.5} * si::metre); +static_assert(min_impl{2} * si::metre - min_impl{1.5} * si::metre == 0.5 * si::metre); static_assert(min_impl{2} * si::kilo - min_impl{1} * si::metre == min_impl{1'999} * si::metre); @@ -182,9 +183,9 @@ static_assert(min_impl{2} * si::kilo - min_impl{1.5} * s static_assert(2 * si::kilo - min_impl{1} * si::metre == min_impl{1'999} * si::metre); static_assert(2 * si::kilo - min_impl{1.5} * si::metre == min_impl{1998.5} * si::metre); static_assert(min_impl{2} * si::kilo - 1 * si::metre == min_impl{1'999} * si::metre); -static_assert(min_impl{2} * si::kilo - double{1.5} * si::metre == min_impl{1998.5} * si::metre); +static_assert(min_impl{2} * si::kilo - 1.5 * si::metre == min_impl{1998.5} * si::metre); static_assert(min_impl{2} * si::kilo - min_impl{1} * si::metre == 1'999 * si::metre); -static_assert(min_impl{2} * si::kilo - min_impl{1.5} * si::metre == double{1998.5} * si::metre); +static_assert(min_impl{2} * si::kilo - min_impl{1.5} * si::metre == 1998.5 * si::metre); static_assert(min_impl{2'000} * si::metre - min_impl{1} * si::kilo == min_impl{1'000} * si::metre); @@ -193,8 +194,7 @@ static_assert(min_impl{2'000} * si::metre - min_impl{1.5} * si::kil static_assert(2'000 * si::metre - min_impl{1} * si::kilo == min_impl{1'000} * si::metre); static_assert(2'000 * si::metre - min_impl{1.5} * si::kilo == min_impl{500} * si::metre); static_assert(min_impl{2'000} * si::metre - 1 * si::kilo == min_impl{1'000} * si::metre); -static_assert(min_impl{2'000} * si::metre - double{1.5} * si::kilo == - min_impl{500} * si::metre); +static_assert(min_impl{2'000} * si::metre - 1.5 * si::kilo == min_impl{500} * si::metre); static_assert(min_impl{2'000} * si::metre - min_impl{1} * si::kilo == 1'000 * si::metre); static_assert(min_impl{2'000} * si::metre - min_impl{1.5} * si::kilo == double{500} * si::metre); @@ -225,7 +225,7 @@ static_assert(min_impl{123} * si::metre / (2. * one) == min_impl{61 static_assert(123 * si::metre / (min_impl(2.) * one) == min_impl{61.5} * si::metre); static_assert(min_impl{123} * si::metre / (min_impl{2.} * si::metre) == 61.5 * one); -static_assert(min_impl{123} * si::metre / (double{2.} * si::metre) == 61.5 * one); +static_assert(min_impl{123} * si::metre / (2. * si::metre) == 61.5 * one); static_assert(123 * si::metre / (min_impl{2.} * si::metre) == 61.5 * one); #endif diff --git a/test/static/quantity_point_test.cpp b/test/static/quantity_point_test.cpp index 26658545..27016618 100644 --- a/test/static/quantity_point_test.cpp +++ b/test/static/quantity_point_test.cpp @@ -835,7 +835,7 @@ static_assert((tower_peak + 42 * m).point_for(tower_peak).quantity_from(tower_pe static_assert((mean_sea_level + 42 * m).point_for(tower_peak).quantity_from(tower_peak) == -42 * m); static_assert((ground_level + 84 * m).point_for(tower_peak).quantity_from(tower_peak) == 42 * m); -static_assert(is_of_type<(ground_level + isq::height(short(42) * m)).point_for(mean_sea_level), +static_assert(is_of_type<(ground_level + isq::height(short{42} * m)).point_for(mean_sea_level), quantity_point>); @@ -938,7 +938,8 @@ static_assert(same_ground_level2_qp.quantity_ref_from(same_ground_level2) == 1 * //////////////////////// static_assert(([]() { - quantity_point l1{mean_sea_level + 1 * m}, l2{mean_sea_level + 2 * m}; + const quantity_point l1{mean_sea_level + 1 * m}; + quantity_point l2{mean_sea_level + 2 * m}; return l2 = l1; }()) .quantity_from(mean_sea_level) == 1 * m); @@ -950,7 +951,7 @@ static_assert(([]() { .quantity_from(mean_sea_level) == 1 * m); static_assert(([]() { quantity_point l1{mean_sea_level + 1 * m}, l2{mean_sea_level + 2 * m}; - return l2 = std::move(l1); + return l2 = std::move(l1); // NOLINT(*-move-const-arg) }()) .quantity_from(mean_sea_level) == 1 * m); @@ -960,19 +961,19 @@ static_assert(([]() { //////////////////// static_assert([](auto v) { - auto vv = v++; + auto vv = v++; // NOLINT(bugprone-inc-dec-in-conditions) return std::pair(v, vv); }(mean_sea_level + 123 * m) == std::pair(mean_sea_level + 124 * m, quantity_point(mean_sea_level + 123 * m))); static_assert([](auto v) { - auto vv = ++v; + auto vv = ++v; // NOLINT(bugprone-inc-dec-in-conditions) return std::pair(v, vv); }(mean_sea_level + 123 * m) == std::pair(mean_sea_level + 124 * m, mean_sea_level + 124 * m)); static_assert([](auto v) { - auto vv = v--; + auto vv = v--; // NOLINT(bugprone-inc-dec-in-conditions) return std::pair(v, vv); }(mean_sea_level + 123 * m) == std::pair(mean_sea_level + 122 * m, mean_sea_level + 123 * m)); static_assert([](auto v) { - auto vv = --v; + auto vv = --v; // NOLINT(bugprone-inc-dec-in-conditions) return std::pair(v, vv); }(mean_sea_level + 123 * m) == std::pair(mean_sea_level + 122 * m, mean_sea_level + 122 * m)); @@ -1302,32 +1303,32 @@ static_assert(is_of_type<(1 * m + tower_peak) - (1 * m + other_ground_level), qu // check for integral types promotion -static_assert(is_same_v); -static_assert(is_same_v); -static_assert(is_same_v); -static_assert(is_same_v); -static_assert(((mean_sea_level + std::uint8_t(128) * m) + std::uint8_t(128) * m) +static_assert(((mean_sea_level + std::uint8_t{128} * m) + std::uint8_t{128} * m) .quantity_from(mean_sea_level) - .numerical_value_in(m) == std::uint8_t(128) + std::uint8_t(128)); -static_assert((std::uint8_t(128) * m + (mean_sea_level + std::uint8_t(128) * m)) + .numerical_value_in(m) == std::uint8_t{128} + std::uint8_t{128}); +static_assert((std::uint8_t{128} * m + (mean_sea_level + std::uint8_t{128} * m)) .quantity_from(mean_sea_level) - .numerical_value_in(m) == std::uint8_t(128) + std::uint8_t(128)); + .numerical_value_in(m) == std::uint8_t{128} + std::uint8_t{128}); static_assert( - ((mean_sea_level + std::uint8_t(0) * m) - std::uint8_t(1) * m).quantity_from(mean_sea_level).numerical_value_in(m) == - std::uint8_t(0) - std::uint8_t(1)); -static_assert(((mean_sea_level + std::uint8_t(0) * m) - (mean_sea_level + std::uint8_t(1) * m)).numerical_value_in(m) == - std::uint8_t(0) - std::uint8_t(1)); + ((mean_sea_level + std::uint8_t{0} * m) - std::uint8_t{1} * m).quantity_from(mean_sea_level).numerical_value_in(m) == + std::uint8_t{0} - std::uint8_t{1}); +static_assert(((mean_sea_level + std::uint8_t{0} * m) - (mean_sea_level + std::uint8_t{1} * m)).numerical_value_in(m) == + std::uint8_t{0} - std::uint8_t{1}); // different representation types static_assert(is_of_type<(mean_sea_level + 1. * m) + 1 * m, quantity_point>); @@ -1676,5 +1677,4 @@ static_assert(invalid_addition(5 * isq::activity[Bq], 10 / (2 * isq::time[s]), q static_assert(invalid_subtraction(quantity_point{5 * isq::activity[Bq]}, 10 / (2 * isq::time[s]), 5 * isq::frequency[Hz])); - } // namespace diff --git a/test/static/quantity_test.cpp b/test/static/quantity_test.cpp index ca29f504..adc2b96f 100644 --- a/test/static/quantity_test.cpp +++ b/test/static/quantity_test.cpp @@ -277,11 +277,12 @@ struct derived_quantity : quantity { R::operator=(std::move(t)); return *this; } - - constexpr operator R&() & noexcept { return *this; } - constexpr operator const R&() const& noexcept { return *this; } - constexpr operator R&&() && noexcept { return *this; } - constexpr operator const R&&() const&& noexcept { return *this; } + // NOLINTBEGIN(google-explicit-constructor, hicpp-explicit-conversions) + constexpr explicit(false) operator R&() & noexcept { return *this; } + constexpr explicit(false) operator const R&() const& noexcept { return *this; } + constexpr explicit(false) operator R&&() && noexcept { return *this; } + constexpr explicit(false) operator const R&&() const&& noexcept { return *this; } + // NOLINTEND(google-explicit-constructor, hicpp-explicit-conversions) }; static_assert(Quantity, "NTTP type description">>); @@ -320,19 +321,19 @@ static_assert(quantity{24h}.quantity_spec == kind_of); //////////////////////// static_assert([] { - auto l1(1 * m), l2(2 * m); + auto l1 = 1 * m, l2 = 2 * m; return l2 = l1; }() .numerical_value_in(m) == 1); static_assert([] { - const auto l1(1 * m); - auto l2(2 * m); + const auto l1 = 1 * m; + auto l2 = 2 * m; return l2 = l1; }() .numerical_value_in(m) == 1); static_assert([]() { - auto l1(1 * m), l2(2 * m); - return l2 = std::move(l1); + auto l1 = 1 * m, l2 = 2 * m; + return l2 = std::move(l1); // NOLINT(*-move-const-arg) }() .numerical_value_in(m) == 1); @@ -347,19 +348,19 @@ static_assert((+(-123 * m)).numerical_value_in(m) == -123); static_assert((-(-123 * m)).numerical_value_in(m) == 123); static_assert([](auto v) { - auto vv = v++; + const auto vv = v++; // NOLINT(bugprone-inc-dec-in-conditions) return std::pair(v, vv); }(123 * m) == std::pair(124 * m, 123 * m)); static_assert([](auto v) { - auto vv = ++v; + const auto vv = ++v; // NOLINT(bugprone-inc-dec-in-conditions) return std::pair(v, vv); }(123 * m) == std::pair(124 * m, 124 * m)); static_assert([](auto v) { - auto vv = v--; + const auto vv = v--; // NOLINT(bugprone-inc-dec-in-conditions) return std::pair(v, vv); }(123 * m) == std::pair(122 * m, 123 * m)); static_assert([](auto v) { - auto vv = --v; + const auto vv = --v; // NOLINT(bugprone-inc-dec-in-conditions) return std::pair(v, vv); }(123 * m) == std::pair(122 * m, 122 * m)); @@ -390,12 +391,12 @@ static_assert((2.5 * m *= 3 * one).numerical_value_in(m) == 7.5); static_assert((7.5 * m /= 3 * one).numerical_value_in(m) == 2.5); static_assert((3500 * m %= 1 * km).numerical_value_in(m) == 500); -// static_assert((std::uint8_t(255) * m %= 256 * m).numerical_value_in(m) == [] { +// static_assert((std::uint8_t{255} * m %= 256 * m).numerical_value_in(m) == [] { // std::uint8_t ui(255); // return ui %= 256; // }()); // UB // TODO: Fix -static_assert((std::uint8_t(255) * m %= 257 * m).numerical_value_in(m) != [] { +static_assert((std::uint8_t{255}* m %= 257 * m).numerical_value_in(m) != [] { std::uint8_t ui(255); return ui %= 257; }()); @@ -538,14 +539,14 @@ static_assert(is_of_type<1 * km % (300 * m), quantity>); static_assert(is_of_type<4 * one % (2 * one), quantity>); // check for integral types promotion -static_assert(is_same_v); -static_assert(is_same_v); -static_assert((std::uint8_t(128) * m + std::uint8_t(128) * m).numerical_value_in(m) == - std::uint8_t(128) + std::uint8_t(128)); -static_assert((std::uint8_t(0) * m - std::uint8_t(1) * m).numerical_value_in(m) == std::uint8_t(0) - std::uint8_t(1)); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert((std::uint8_t{128} * m + std::uint8_t{128} * m).numerical_value_in(m) == + std::uint8_t{128} + std::uint8_t{128}); +static_assert((std::uint8_t{0} * m - std::uint8_t{1} * m).numerical_value_in(m) == std::uint8_t{0} - std::uint8_t{1}); static_assert( - is_same_v); + is_same_v); // different representation types static_assert(is_of_type<1. * m + 1 * m, quantity>); @@ -767,14 +768,14 @@ static_assert(is_same_v); static_assert(1 * one - 30 * percent == (100 - 30) * percent); static_assert(1 * one + 30 * percent == (100 + 30) * percent); -static_assert(is_same_v); -static_assert(is_same_v); -static_assert((std::uint8_t(128) * one + std::uint8_t(128) * one).numerical_value_in(one) == - std::uint8_t(128) + std::uint8_t(128)); -static_assert((std::uint8_t(0) * one - std::uint8_t(1) * one).numerical_value_in(one) == - std::uint8_t(0) - std::uint8_t(1)); -static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert((std::uint8_t{128} * one + std::uint8_t{128} * one).numerical_value_in(one) == + std::uint8_t{128} + std::uint8_t{128}); +static_assert((std::uint8_t{0} * one - std::uint8_t{1} * one).numerical_value_in(one) == + std::uint8_t{0} - std::uint8_t{1}); +static_assert(is_same_v); static_assert(2 * one * (1 * m) == 2 * m); static_assert(2 * one / (1 * m) == 2 / (1 * m)); diff --git a/test/static/test_tools.h b/test/static/test_tools.h index 73f79613..051fc31c 100644 --- a/test/static/test_tools.h +++ b/test/static/test_tools.h @@ -29,6 +29,7 @@ template inline constexpr bool is_of_type = std::is_same_v, T>; +// NOLINTBEGIN(cppcoreguidelines-macro-usage) #ifdef MP_UNITS_API_NO_CRTP #define QUANTITY_SPEC_(name, ...) \ @@ -42,3 +43,4 @@ inline constexpr bool is_of_type = std::is_same_v(mag<60> * s static_assert(unit_symbol(mag_ratio<1, 18> * metre / second) == "[1/18] m/s"); // derived units -static_assert(unit_symbol(one) == ""); +static_assert(unit_symbol(one) == ""); // NOLINT(readability-container-size-empty) static_assert(unit_symbol(percent) == "%"); static_assert(unit_symbol(per_mille) == "‰"); static_assert(unit_symbol(per_mille) == "%o"); @@ -122,7 +122,7 @@ static_assert(unit_symbol(cubic(metre)) == "m³"); static_assert(unit_symbol(cubic(metre)) == "m^3"); static_assert(unit_symbol(kilo * metre) == "km m"); static_assert(unit_symbol(kilo * metre) == "km⋅m"); -static_assert(unit_symbol(metre / metre) == ""); +static_assert(unit_symbol(metre / metre) == ""); // NOLINT(readability-container-size-empty) static_assert(unit_symbol(kilo / metre) == "km/m"); static_assert(unit_symbol(kilo / metre) == "km m⁻¹"); static_assert(unit_symbol(kilo / metre) ==