/* * This file is part of the DXX-Rebirth project . * It is copyright by its individual contributors, as recorded in the * project's Git history. See COPYING.txt at the top level for license * terms and a link to the Git history. */ #pragma once #include #include #include "dxxsconf.h" #include "compiler-type_traits.h" #include "pack.h" #ifdef DXX_HAVE_BUILTIN_CONSTANT_P #define DXX_VALPTRIDX_STATIC_CHECK(E,F,S) \ ((void)(dxx_builtin_constant_p((E)) && !(E) && \ (DXX_ALWAYS_ERROR_FUNCTION(F,S), 0))) #define DXX_VALPTRIDX_INLINE_STATIC_CHECK inline #else #define DXX_VALPTRIDX_STATIC_CHECK(E,F,S) \ ((void)0) #define DXX_VALPTRIDX_INLINE_STATIC_CHECK #endif #ifdef DXX_HAVE_CXX11_REF_QUALIFIER #define DXX_VALPTRIDX_REF_QUALIFIER_LVALUE & #else #define DXX_VALPTRIDX_REF_QUALIFIER_LVALUE #endif #define DXX_VALPTRIDX_CHECK(E,S,success,failure) \ ( \ DXX_VALPTRIDX_STATIC_CHECK(E,dxx_trap_##failure,S), \ (E) ? success : throw failure(S) \ ) /* Never used with an actual void, but needed for proper two-stage * lookup. */ template typename tt::enable_if::value, void>::type get_global_array(T *); template class valbaseptridxutil_t { protected: struct null_pointer_exception : std::logic_error { null_pointer_exception(const char *s) : std::logic_error(s) {} }; struct index_mismatch_exception : std::logic_error { index_mismatch_exception(const char *s) : std::logic_error(s) {} }; struct index_range_exception : std::out_of_range { index_range_exception(const char *s) : std::out_of_range(s) {} }; typedef P *pointer_type; typedef I index_type; typedef typename tt::remove_const

::type Prc; static constexpr decltype(get_global_array(pointer_type())) get_array() { return get_global_array(pointer_type()); } static const P *check_null_pointer(const P *p) __attribute_warn_unused_result { return DXX_VALPTRIDX_CHECK(p, "NULL pointer used", p, null_pointer_exception); } static Prc *check_null_pointer(Prc *p) __attribute_warn_unused_result { return DXX_VALPTRIDX_CHECK(p, "NULL pointer used", p, null_pointer_exception); } template static DXX_VALPTRIDX_INLINE_STATIC_CHECK __attribute_warn_unused_result index_type check_index_match(const A &a, pointer_type p, index_type s) { return DXX_VALPTRIDX_CHECK(&a[s] == p, "pointer/index mismatch", s, index_mismatch_exception); } template static DXX_VALPTRIDX_INLINE_STATIC_CHECK __attribute_warn_unused_result index_type check_index_range(const A &a, index_type s) { return DXX_VALPTRIDX_CHECK(static_cast(s) < a.size(), "invalid index used in array subscript", s, index_range_exception); } }; template class vvalptr_t; template class magic_constant> class vvalidx_t; template class magic_constant> class validx_t; template < bool require_valid, typename P, typename I, template class magic_constant, typename Prc = typename tt::remove_const

::type> struct valptridx_template_t; template class valptr_t : protected valbaseptridxutil_t { typedef valbaseptridxutil_t valutil; protected: typedef typename valutil::Prc Prc; typedef valptr_t valptr_type; using valutil::check_null_pointer; using valutil::check_index_range; public: const P *unchecked_const_pointer() const { return p; } /* Indirect through the extra version to get a good compiler * backtrace when misuse happens. */ Prc *unchecked_mutable_pointer(const P *) const = delete; Prc *unchecked_mutable_pointer(Prc *) const { return p; } Prc *unchecked_mutable_pointer() const { return unchecked_mutable_pointer(static_cast

(nullptr)); } typedef typename valutil::pointer_type pointer_type; typedef P &reference; valptr_t() = delete; valptr_t(I) = delete; valptr_t(vvalptr_t &&) = delete; valptr_t(vvalptr_t &&) = delete; valptr_t(std::nullptr_t) : p(nullptr) {} template