diff --git a/include/gsl.h b/include/gsl.h index 0575d57..ad064ba 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -20,6 +20,7 @@ #define GSL_GSL_H #include "gsl_assert.h" // Ensures/Expects +#include "gsl_util.h" // finally()/narrow()/narrow_cast()... #include "span.h" // span, strided_span... #include "string_span.h" // zstring, string_span, zstring_builder... #include @@ -57,56 +58,6 @@ using std::shared_ptr; template using owner = T; -// -// GSL.util: utilities -// - -// final_act allows you to ensure something gets run at the end of a scope -template -class final_act -{ -public: - explicit final_act(F f) noexcept : f_(std::move(f)), invoke_(true) {} - - 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; - - ~final_act() noexcept { if (invoke_) f_(); } - -private: - F f_; - bool invoke_; -}; - -// finally() - convenience function to generate a final_act -template -final_act finally(const F &f) noexcept { return final_act(f); } - -template -final_act finally(F &&f) noexcept { return final_act(std::forward(f)); } - -// narrow_cast(): a searchable way to do narrowing casts of values -template -T narrow_cast(U u) noexcept { return static_cast(u); } - -struct narrowing_error : public std::exception {}; -// narrow() : a checked version of narrow_cast() that throws if the cast changed the value -template -T narrow(U u) { T t = narrow_cast(u); if (static_cast(t) != u) throw narrowing_error(); return t; } - -// -// at() - Bounds-checked way of accessing static arrays, std::array, std::vector -// -template -T& at(T(&arr)[N], size_t index) { Expects(index < N); return arr[index]; } - -template -T& at(std::array& arr, size_t index) { Expects(index < N); return arr[index]; } - -template -typename Cont::value_type& at(Cont& cont, size_t index) { Expects(index < cont.size()); return cont[index]; } - // // not_null diff --git a/include/gsl_util.h b/include/gsl_util.h new file mode 100644 index 0000000..b6f56ce --- /dev/null +++ b/include/gsl_util.h @@ -0,0 +1,132 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// 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 + +#ifndef GSL_UTIL_H +#define GSL_UTIL_H + +#include "gsl_assert.h" // Ensures/Expects +#include +#include +#include + +#ifdef _MSC_VER + +// No MSVC does constexpr fully yet +#pragma push_macro("constexpr") +#define constexpr + +// MSVC 2013 workarounds +#if _MSC_VER <= 1800 +// noexcept is not understood +#pragma push_macro("noexcept") +#define noexcept + +// turn off some misguided warnings +#pragma warning(push) +#pragma warning(disable: 4351) // warns about newly introduced aggregate initializer behavior + +#endif // _MSC_VER <= 1800 + +#endif // _MSC_VER + + +namespace gsl +{ +// +// GSL.util: utilities +// + +// final_act allows you to ensure something gets run at the end of a scope +template +class final_act +{ +public: + explicit final_act(F f) noexcept + : f_(std::move(f)), invoke_(true) + {} + + 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; + + ~final_act() noexcept { if (invoke_) f_(); } + +private: + F f_; + bool invoke_; +}; + +// finally() - convenience function to generate a final_act +template +final_act finally(const F &f) +noexcept { return final_act(f); } + +template +final_act finally(F &&f) noexcept +{ return final_act(std::forward(f)); } + +// narrow_cast(): a searchable way to do narrowing casts of values +template +constexpr T narrow_cast(U u) noexcept +{ return static_cast(u); } + +struct narrowing_error : public std::exception {}; + +// narrow() : a checked version of narrow_cast() that throws if the cast changed the value +template +T narrow(U u) +{ T t = narrow_cast(u); if (static_cast(t) != u) throw narrowing_error(); return t; } + +// +// at() - Bounds-checked way of accessing static arrays, std::array, std::vector +// +template +constexpr T& at(T(&arr)[N], size_t index) +{ Expects(index < N); return arr[index]; } + +template +constexpr T& at(std::array& arr, size_t index) +{ Expects(index < N); return arr[index]; } + +template +constexpr typename Cont::value_type& at(Cont& cont, size_t index) +{ Expects(index < cont.size()); return cont[index]; } + +} // namespace gsl + + +#ifdef _MSC_VER + +#undef constexpr +#pragma pop_macro("constexpr") + +#if _MSC_VER <= 1800 + +#undef noexcept +#pragma pop_macro("noexcept") + +#pragma warning(pop) + +#endif // _MSC_VER <= 1800 + +#endif // _MSC_VER + +#endif // GSL_UTIL_H diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index fe7a831..a524d01 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -33,7 +33,7 @@ if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/unittest-cpp) endif() function(add_gsl_test name) - add_executable(${name} ${name}.cpp) + add_executable(${name} ${name}.cpp ../include/gsl.h ../include/gsl_assert.h ../include/gsl_util.h ../include/span.h ../include/string_span.h) target_link_libraries(${name} UnitTest++) install(TARGETS ${name} RUNTIME DESTINATION bin