diff options
author | Johel Ernesto Guerrero Peña <johelegp@gmail.com> | 2021-06-24 01:28:45 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-24 01:28:45 +0300 |
commit | 8a4b9ed0bf643726ce625678a17b1fc40d90870c (patch) | |
tree | 166001718f7fa975d62f6d3809c6c7553b157444 | |
parent | b26f6d5ec7b043f9d459c1dfdd6da4d930d4e9b4 (diff) |
feat: narrow for non totally ordered types (#986)
-rw-r--r-- | include/gsl/narrow | 19 | ||||
-rw-r--r-- | tests/utils_tests.cpp | 5 |
2 files changed, 23 insertions, 1 deletions
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 <class T, class U>
+template <class T, class U, typename std::enable_if<std::is_arithmetic<T>::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 <class T, class U, typename std::enable_if<!std::is_arithmetic<T>::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<T>(u);
+
+ if (static_cast<U>(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 <gtest/gtest.h> #include <algorithm> // for move +#include <complex> #include <cstddef> // for std::ptrdiff_t #include <functional> // for reference_wrapper, _Bind_helper<>::type #include <gsl/narrow> // for narrow, narrowing_error @@ -144,5 +145,9 @@ TEST(utils_tests, narrow) n = -42; EXPECT_THROW(narrow<unsigned>(n), narrowing_error); + + EXPECT_TRUE( + narrow<std::complex<float>>(std::complex<double>(4, 2)) == std::complex<float>(4, 2)); + EXPECT_THROW(narrow<std::complex<float>>(std::complex<double>(4.2)), narrowing_error); } #endif // GSL_KERNEL_MODE |