summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/plib/pgsl.h
diff options
context:
space:
mode:
author Roberto Fresca <robbie@robertofresca.com>2020-06-13 15:58:27 +0200
committer Roberto Fresca <robbie@robertofresca.com>2020-06-13 15:58:27 +0200
commit284f196df1c65a91eb38a5a9f31a2da7fb86a1ac (patch)
treed29473e4024dce305d0ee3bb957a663420417312 /src/lib/netlist/plib/pgsl.h
parent52b8d5fd2b656c317e589da93467c33be74e76ea (diff)
parente949e9c29de82ee7c32692e7b65da05dd22bdc9d (diff)
Merge branch 'master' of https://github.com/mamedev/mame
Diffstat (limited to 'src/lib/netlist/plib/pgsl.h')
-rw-r--r--src/lib/netlist/plib/pgsl.h105
1 files changed, 105 insertions, 0 deletions
diff --git a/src/lib/netlist/plib/pgsl.h b/src/lib/netlist/plib/pgsl.h
new file mode 100644
index 00000000000..ab7798071a5
--- /dev/null
+++ b/src/lib/netlist/plib/pgsl.h
@@ -0,0 +1,105 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+
+#ifndef PGSL_H_
+#define PGSL_H_
+
+///
+/// \file pgsl.h
+///
+/// This core guidelines gsl implementation currently provides only enough
+/// functionality to syntactically support a very limited number of the
+/// gsl specification.
+///
+/// Going forward this approach may be extended.
+///
+
+#include "pconfig.h"
+#include "pexception.h"
+#include "ptypes.h"
+
+#include <exception>
+#include <type_traits>
+#include <utility>
+
+#if defined(__has_builtin) // clang and gcc 10
+ #if __has_builtin(__builtin_unreachable)
+ #define gsl_Expects(e) ((e) ? static_cast<void>(0) : __builtin_unreachable())
+ #endif
+#elif defined(__GNUC__) && !(defined( __CUDACC__ ) && defined( __CUDA_ARCH__ ))
+ #define gsl_Expects(e) ((e) ? static_cast<void>(0) : __builtin_unreachable())
+#elif defined(_MSC_VER)
+ #define gsl_Expects(e) __assume(e)
+#else
+ #define gsl_Expects(e) ((e) ? static_cast<void>(0) : static_cast<void>(0))
+#endif
+
+#undef gsl_Expects
+#define gsl_Expects(e) do {} while (0)
+#define gsl_Ensures(e) gsl_Expects(e)
+
+namespace plib {
+ namespace pgsl {
+
+ struct narrowing_error : public std::exception {};
+
+ template <typename T>
+ using owner = T;
+
+ template <typename T>
+ using not_null = T;
+
+ /// \brief perform a narrowing cast without checks
+ ///
+ template <typename T, typename O>
+ inline constexpr T narrow_cast(O && v) noexcept
+ {
+ static_assert(plib::is_arithmetic<T>::value && std::is_convertible<std::remove_reference_t<O>, T>::value, "narrow cast expects conversion between arithmetic types");
+ return static_cast<T>(std::forward<O>(v));
+ }
+
+ /// \brief perform a narrowing cast terminating if loss of precision
+ ///
+ /// The c++ core guidelines require the narrow function to raise an error
+ /// This will make narrow noexcept(false). This has shown to have a
+ /// measurable impact on performance and thus we deviate we deviate from
+ /// the standard here.
+ ///
+ template <typename T, typename O>
+ inline T narrow(O && v) noexcept
+ {
+ static_assert(plib::is_arithmetic<T>::value && std::is_convertible<std::remove_reference_t<O>, T>::value, "narrow cast expects conversion between arithmetic types");
+
+ const auto val = static_cast<T>(std::forward<O>(v));
+ if( v == static_cast<std::remove_reference_t<O>>(val))
+ {
+ return val;
+ }
+
+ plib::terminate("narrowing_error");
+ // throw narrowing_error();
+ }
+
+ } // namespace pgsl
+
+ /// \brief downcast from base tpye to derived type
+ ///
+ /// The cpp core guidelines require a very careful use of static cast
+ /// for downcast operations. This template is used to identify these uses
+ /// and later for debug builds use dynamic_cast.
+ ///
+ template <typename D, typename B>
+ inline constexpr D downcast(B && b) noexcept
+ {
+ static_assert(std::is_pointer<D>::value || std::is_reference<D>::value, "downcast only supports pointers or reference for derived");
+ static_assert(std::is_pointer<B>::value || std::is_reference<B>::value, "downcast only supports pointers or reference for base");
+ return static_cast<D>(std::forward<B>(b));
+ }
+
+ using pgsl::narrow_cast;
+} // namespace plib
+
+//FIXME: This is the place to use more complete implementations
+namespace gsl = plib::pgsl;
+
+#endif // PGSL_H_