diff --git a/include/gsl_util.h b/include/gsl_util.h index e38868c..316f2a1 100644 --- a/include/gsl_util.h +++ b/include/gsl_util.h @@ -1,17 +1,17 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (c) 2015 Microsoft Corporation. All rights reserved. -// -// This code is licensed under the MIT License (MIT). -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// /////////////////////////////////////////////////////////////////////////////// #pragma once @@ -22,23 +22,25 @@ #include "gsl_assert.h" // Ensures/Expects #include #include +#include #include #ifdef _MSC_VER // No MSVC does constexpr fully yet #pragma push_macro("constexpr") -#define constexpr +#define constexpr // MSVC 2013 workarounds #if _MSC_VER <= 1800 -// noexcept is not understood +// noexcept is not understood #pragma push_macro("noexcept") -#define noexcept +#define noexcept // turn off some misguided warnings #pragma warning(push) #pragma warning(disable: 4351) // warns about newly introduced aggregate initializer behavior +#pragma warning(disable: 4127) // conditional expression is constant #endif // _MSC_VER <= 1800 @@ -63,7 +65,7 @@ public: final_act(final_act&& other) noexcept : f_(std::move(other.f_)), invoke_(other.invoke_) { other.invoke_ = false; } - + final_act(const final_act&) = delete; final_act& operator=(const final_act&) = delete; @@ -90,15 +92,29 @@ inline constexpr T narrow_cast(U u) noexcept struct narrowing_error : public std::exception {}; +namespace details +{ + template + struct is_same_signedness : public std::integral_constant::value == std::is_signed::value> + {}; +} + // narrow() : a checked version of narrow_cast() that throws if the cast changed the value template inline T narrow(U u) -{ T t = narrow_cast(u); if (static_cast(t) != u) throw narrowing_error(); return t; } +{ + T t = narrow_cast(u); + if (static_cast(t) != u) + throw narrowing_error(); + if (!details::is_same_signedness::value && ((t < T{}) != (u < U{}))) + throw narrowing_error(); + return t; +} // // at() - Bounds-checked way of accessing static arrays, std::array, std::vector // -template +template constexpr T& at(T(&arr)[N], size_t index) { Expects(index < N); return arr[index]; } @@ -122,7 +138,7 @@ constexpr typename Cont::value_type& at(Cont& cont, size_t index) #undef noexcept #pragma pop_macro("noexcept") - + #pragma warning(pop) #endif // _MSC_VER <= 1800 diff --git a/tests/utils_tests.cpp b/tests/utils_tests.cpp index 9406e6b..a46d6e4 100644 --- a/tests/utils_tests.cpp +++ b/tests/utils_tests.cpp @@ -1,20 +1,20 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (c) 2015 Microsoft Corporation. All rights reserved. -// -// This code is licensed under the MIT License (MIT). -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// /////////////////////////////////////////////////////////////////////////////// -#include +#include #include #include @@ -95,8 +95,21 @@ SUITE(utils_tests) char c = narrow(n); CHECK(c == 120); - n = 300; + n = 300; CHECK_THROW(narrow(n), narrowing_error); + + const auto int32_max = std::numeric_limits::max(); + const auto int32_min = std::numeric_limits::min(); + + CHECK(narrow(int32_t(0)) == 0); + CHECK(narrow(int32_t(1)) == 1); + CHECK(narrow(int32_max) == int32_max); + + CHECK_THROW(narrow(int32_t(-1)), narrowing_error); + CHECK_THROW(narrow(int32_min), narrowing_error); + + n = -42; + CHECK_THROW(narrow(n), narrowing_error); } }