From 8a4b9ed0bf643726ce625678a17b1fc40d90870c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Wed, 23 Jun 2021 18:28:45 -0400 Subject: [PATCH] feat: narrow for non totally ordered types (#986) --- include/gsl/narrow | 19 ++++++++++++++++++- tests/utils_tests.cpp | 5 +++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/include/gsl/narrow b/include/gsl/narrow index 67aac05..40016d1 100644 --- a/include/gsl/narrow +++ b/include/gsl/narrow @@ -26,7 +26,7 @@ struct narrowing_error : public std::exception }; // narrow() : a checked version of narrow_cast() that throws if the cast changed the value -template +template ::value>::type* = nullptr> // clang-format off GSL_SUPPRESS(type.1) // NO-FORMAT: attribute GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false) @@ -45,5 +45,22 @@ GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recogn return t; } + +template ::value>::type* = nullptr> +// clang-format off +GSL_SUPPRESS(type.1) // NO-FORMAT: attribute +GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false) + // clang-format on + constexpr T narrow(U u) noexcept(false) +{ + const T t = narrow_cast(u); + + if (static_cast(t) != u) + { + throw narrowing_error{}; + } + + return t; +} } // namespace gsl #endif // GSL_NARROW_H diff --git a/tests/utils_tests.cpp b/tests/utils_tests.cpp index 0585c79..39b4ca2 100644 --- a/tests/utils_tests.cpp +++ b/tests/utils_tests.cpp @@ -17,6 +17,7 @@ #include #include // for move +#include #include // for std::ptrdiff_t #include // for reference_wrapper, _Bind_helper<>::type #include // for narrow, narrowing_error @@ -144,5 +145,9 @@ TEST(utils_tests, narrow) n = -42; EXPECT_THROW(narrow(n), narrowing_error); + + EXPECT_TRUE( + narrow>(std::complex(4, 2)) == std::complex(4, 2)); + EXPECT_THROW(narrow>(std::complex(4.2)), narrowing_error); } #endif // GSL_KERNEL_MODE