mirror of https://github.com/procxx/kepka.git
				
				
				
			
		
			
				
	
	
		
			152 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			152 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
///////////////////////////////////////////////////////////////////////////////
 | 
						|
//
 | 
						|
// 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.
 | 
						|
//
 | 
						|
///////////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
#ifndef GSL_UTIL_H
 | 
						|
#define GSL_UTIL_H
 | 
						|
 | 
						|
#include <gsl/gsl_assert> // Ensures/Expects
 | 
						|
 | 
						|
#include <array>
 | 
						|
#include <exception>
 | 
						|
#include <type_traits>
 | 
						|
#include <utility>
 | 
						|
 | 
						|
#if defined(_MSC_VER)
 | 
						|
 | 
						|
#pragma warning(push)
 | 
						|
#pragma warning(disable : 4127) // conditional expression is constant
 | 
						|
 | 
						|
#if _MSC_VER < 1910
 | 
						|
#pragma push_macro("constexpr")
 | 
						|
#define constexpr /*constexpr*/
 | 
						|
#endif                          // _MSC_VER < 1910
 | 
						|
#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 F>
 | 
						|
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 <class F>
 | 
						|
inline final_act<F> finally(const F& f) noexcept
 | 
						|
{
 | 
						|
    return final_act<F>(f);
 | 
						|
}
 | 
						|
 | 
						|
template <class F>
 | 
						|
inline final_act<F> finally(F&& f) noexcept
 | 
						|
{
 | 
						|
    return final_act<F>(std::forward<F>(f));
 | 
						|
}
 | 
						|
 | 
						|
// narrow_cast(): a searchable way to do narrowing casts of values
 | 
						|
template <class T, class U>
 | 
						|
inline constexpr T narrow_cast(U&& u) noexcept
 | 
						|
{
 | 
						|
    return static_cast<T>(std::forward<U>(u));
 | 
						|
}
 | 
						|
 | 
						|
struct narrowing_error : public std::exception
 | 
						|
{
 | 
						|
};
 | 
						|
 | 
						|
namespace details
 | 
						|
{
 | 
						|
    template <class T, class U>
 | 
						|
    struct is_same_signedness
 | 
						|
        : public std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value>
 | 
						|
    {
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
 | 
						|
template <class T, class U>
 | 
						|
inline T narrow(U u)
 | 
						|
{
 | 
						|
    T t = narrow_cast<T>(u);
 | 
						|
    if (static_cast<U>(t) != u) throw narrowing_error();
 | 
						|
    if (!details::is_same_signedness<T, U>::value && ((t < T{}) != (u < U{})))
 | 
						|
        throw narrowing_error();
 | 
						|
    return t;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector
 | 
						|
//
 | 
						|
template <class T, std::size_t N>
 | 
						|
inline constexpr T& at(T (&arr)[N], const std::ptrdiff_t index)
 | 
						|
{
 | 
						|
    Expects(index >= 0 && index < narrow_cast<std::ptrdiff_t>(N));
 | 
						|
    return arr[static_cast<std::size_t>(index)];
 | 
						|
}
 | 
						|
 | 
						|
template <class Cont>
 | 
						|
inline constexpr auto at(Cont& cont, const std::ptrdiff_t index) -> decltype(cont[cont.size()])
 | 
						|
{
 | 
						|
    Expects(index >= 0 && index < narrow_cast<std::ptrdiff_t>(cont.size()));
 | 
						|
    using size_type = decltype(cont.size());
 | 
						|
    return cont[static_cast<size_type>(index)];
 | 
						|
}
 | 
						|
 | 
						|
template <class T>
 | 
						|
inline constexpr T at(const std::initializer_list<T> cont, const std::ptrdiff_t index)
 | 
						|
{
 | 
						|
    Expects(index >= 0 && index < narrow_cast<std::ptrdiff_t>(cont.size()));
 | 
						|
    return *(cont.begin() + index);
 | 
						|
}
 | 
						|
 | 
						|
} // namespace gsl
 | 
						|
 | 
						|
#if defined(_MSC_VER)
 | 
						|
#if _MSC_VER < 1910
 | 
						|
#undef constexpr
 | 
						|
#pragma pop_macro("constexpr")
 | 
						|
 | 
						|
#endif // _MSC_VER < 1910
 | 
						|
 | 
						|
#pragma warning(pop)
 | 
						|
 | 
						|
#endif // _MSC_VER
 | 
						|
 | 
						|
#endif // GSL_UTIL_H
 |