diff options
-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 |