Skip to content

Utilities: utilnarrow

4. Utilities
move_owner a helper function that moves one owner to the other
byte either an alias to std::byte or a byte type
final_action a RAII style class that invokes a functor on its destruction
finally a helper function instantiating final_action
GSL_SUPPRESS a macro that takes an argument and turns it into [[gsl::suppress(x)]] or [[gsl::suppress("x")]]
[[implicit]] a "marker" to put on single-argument constructors to explicitly make them non-explicit
index a type to use for all container and array indexing (currently an alias for std::ptrdiff_t)
joining_thread a RAII style version of std::thread that joins
narrow a checked version of narrow_cast; it can throw narrowing_error
narrow_cast a narrowing cast for values and a synonym for static_cast
narrowing_error a custom exception type thrown by narrow()

Read the code

final_action and finally

1、其实就是scope guard

2、finally其实就是object generator

#include <type_traits>      // for is_signed, integral_constant
#include <utility>          // for exchange, forward

//
// make suppress attributes parse for some compilers
// Hopefully temporary until suppression standardization occurs
//
#if defined(__clang__)
#define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
#else
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
#else
#define GSL_SUPPRESS(x)
#endif // _MSC_VER
#endif // __clang__

#if defined(__cplusplus) && (__cplusplus >= 201703L)
#define GSL_NODISCARD [[nodiscard]]
#else
#define GSL_NODISCARD
#endif // defined(__cplusplus) && (__cplusplus >= 201703L)

// final_action allows you to ensure something gets run at the end of a scope
template<class F>
class final_action
{
public:
    static_assert(!std::is_reference<F>::value && !std::is_const<F>::value &&
                    !std::is_volatile<F>::value,
                    "Final_action should store its callable by value");

    explicit final_action(F f) noexcept :
                    f_(std::move(f))
    {
    }

    final_action(final_action &&other) noexcept :
                    f_(std::move(other.f_)), invoke_(std::exchange(other.invoke_, false))
    {
    }

    final_action(const final_action&) = delete;
    final_action& operator=(const final_action&) = delete;
    final_action& operator=(final_action&&) = delete;

    // clang-format off
    GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // terminate if throws
    // clang-format on
    ~final_action() noexcept
    {
        if (invoke_)
            f_();
    }

private:
    F f_;
    bool invoke_ { true };
};

// finally() - convenience function to generate a final_action
template<class F>
GSL_NODISCARD final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type> finally(F &&f) noexcept
{
    return final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type>(std::forward < F > (f));
}

#include  <cassert>
void f(int &i)
{
    i += 1;
}

int main()
{
    int i = 0;
    {
        auto _ = finally([&](){ f(i);});

    }
    assert(i == 1);
}
// g++ test.cpp --std=c++14

index

#include <cstddef>          // for ptrdiff_t, size_t
// index type for all container indexes/subscripts/sizes
using index = std::ptrdiff_t;

at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector

#include <array>
#include <cstddef>          // for ptrdiff_t, size_t
#include <initializer_list> // for initializer_list
#include <type_traits>      // for is_signed, integral_constant
#include <utility>          // for exchange, forward


//
// at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector
//
template <class T, std::size_t N>
// clang-format off
GSL_SUPPRESS(bounds.4)// NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2)// NO-FORMAT: attribute
// clang-format on
constexpr T& at(T (&arr)[N], const index i)
{
    Expects(i >= 0 && i < narrow_cast<index>(N));
    return arr[narrow_cast<std::size_t>(i)];
}

template <class Cont>
// clang-format off
GSL_SUPPRESS(bounds.4)// NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2)// NO-FORMAT: attribute
// clang-format on
constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()])
{
    Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
    using size_type = decltype(cont.size());
    return cont[narrow_cast<size_type>(i)];
}

template <class T>
// clang-format off
GSL_SUPPRESS(bounds.1)// NO-FORMAT: attribute
// clang-format on
constexpr T at(const std::initializer_list<T> cont, const index i)
{
    Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
    return *(cont.begin() + i);
}

narrow_cast

// narrow_cast(): a searchable way to do narrowing casts of values
template <class T, class U>
// clang-format off
GSL_SUPPRESS(type.1)// NO-FORMAT: attribute
// clang-format on
constexpr T narrow_cast(U&& u) noexcept
{
    return static_cast<T>(std::forward<U>(u));
}