From 082bb43edef8c05e7cd1f3e2868eb53f425aa97b Mon Sep 17 00:00:00 2001 From: Kp Date: Fri, 11 Jul 2014 03:14:50 +0000 Subject: [PATCH] Fold valptridx_t features into template --- common/include/valptridx.h | 205 +++++++++++++++++++++---------------- common/main/object.h | 14 ++- 2 files changed, 130 insertions(+), 89 deletions(-) diff --git a/common/include/valptridx.h b/common/include/valptridx.h index ca5d26299..10e9c2347 100644 --- a/common/include/valptridx.h +++ b/common/include/valptridx.h @@ -8,101 +8,134 @@ #include #include "dxxsconf.h" - -/* - * A data type for passing both a pointer and its offset in an - * agreed-upon array. Useful for Segments, Objects. - */ -template -class valptridx_t -{ - valptridx_t() DXX_CXX11_EXPLICIT_DELETE; -public: - typedef T *pointer_type; - typedef I index_type; - pointer_type operator->() const { return p; } - operator pointer_type() const { return p; } - operator const index_type&() const { return i; } - bool operator==(const valptridx_t &rhs) const { return p == rhs.p; } -protected: - valptridx_t(pointer_type t, index_type s) : - p(t), i(s) - { - } - pointer_type p; - index_type i; -}; - -#define _DEFINE_VALPTRIDX_SUBTYPE_HEADER(N,I) \ - template \ - struct N##_template_t : public valptridx_t \ - -#define _DEFINE_VALPTRIDX_SUBTYPE_TYPEDEFS(I) \ - typedef valptridx_t base_type; \ - typedef typename base_type::pointer_type pointer_type; \ - typedef typename base_type::index_type index_type; \ - -#define _DEFINE_VALPTRIDX_SUBTYPE_CTOR2(N,A) \ - N##_template_t(pointer_type t, index_type s) : \ - base_type(t, s) \ - { \ - if (!t) \ - throw std::logic_error("NULL pointer explicit constructor"); \ - if (&A[s] != t) \ - throw std::logic_error("pointer/index mismatch"); \ - } \ - -#define _DEFINE_VALPTRIDX_SUBTYPE_USERTYPE(name,base) \ - struct name : public base { \ - name() DXX_CXX11_EXPLICIT_DELETE; \ - DXX_INHERIT_CONSTRUCTORS(name, base); \ - } \ - -#define _DEFINE_VALPTRIDX_SUBTYPE_USERTYPES(N,P) \ - _DEFINE_VALPTRIDX_SUBTYPE_USERTYPE(N##_t, N##_template_t

); \ - _DEFINE_VALPTRIDX_SUBTYPE_USERTYPE(c##N##_t, N##_template_t

); \ +#include "compiler-type_traits.h" #ifdef DXX_HAVE_BUILTIN_CONSTANT_P #define DXX_VALPTRIDX_STATIC_CHECK(I,E,F,S) \ - if (dxx_builtin_constant_p(I) && !(E)) { \ - void F() __attribute_error(S); \ - F(); \ - } + if (dxx_builtin_constant_p(I) && !(E)) \ + DXX_ALWAYS_ERROR_FUNCTION(F,S) #else #define DXX_VALPTRIDX_STATIC_CHECK(I,E,F,S) \ #endif -#define DEFINE_VALPTRIDX_SUBTYPE(N,P,I,A) \ - _DEFINE_VALPTRIDX_SUBTYPE_HEADER(N,I) \ - { \ - _DEFINE_VALPTRIDX_SUBTYPE_TYPEDEFS(I) \ - _DEFINE_VALPTRIDX_SUBTYPE_CTOR2(N,A) \ - N##_template_t(pointer_type t) : \ - base_type(t, t-A) \ - { \ - DXX_VALPTRIDX_STATIC_CHECK(t, t, dxx_trap_constant_null_pointer, "NULL pointer used"); \ - if (!t) \ - throw std::logic_error("NULL pointer explicit constructor"); \ - if (&A[this->i] != t) \ - throw std::logic_error("unaligned pointer"); \ - } \ - N##_template_t(index_type s) : \ - base_type(&A[s], s) \ - { \ - DXX_VALPTRIDX_STATIC_CHECK(s, static_cast(s) < A.size(), dxx_trap_constant_invalid_index, "invalid index used in array subscript"); \ - if (!(static_cast(s) < A.size())) \ - throw std::out_of_range("index exceeds " #N " range"); \ - } \ - template \ - N##_template_t(const P##_magic_constant_t &) : \ - base_type(static_cast(i) < A.size() ? &A[i] : NULL, i) \ - { \ - } \ +template +void get_global_array(T *); + +/* + * A data type for passing both a pointer and its offset in an + * agreed-upon array. Useful for Segments, Objects. + */ +template class magic_constant> +class valptridx_t +{ + typedef valptridx_t this_type; +public: + 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 T *pointer_type; + typedef I index_type; + pointer_type operator->() const { return p; } + operator pointer_type() const { return p; } + operator const index_type&() const { return i; } + template + bool operator==(const magic_constant &) const + { + return i == v; + } + bool operator==(const pointer_type &rhs) const { return p == rhs; } + bool operator==(const index_type &rhs) const { return i == rhs; } + // Compatibility hack since some object numbers are in int, not + // short + bool operator==(const int &rhs) const { return i == rhs; } + template + bool operator!=(const R &rhs) const + { + return !(*this == rhs); + } + bool operator==(const valptridx_t &rhs) const { return p == rhs.p && i == rhs.i; } + template + typename tt::enable_if::value, bool>::type operator==(U) const = delete; + valptridx_t() = delete; + valptridx_t(const valptridx_t::type, I, magic_constant> &t) : + p(t.p), i(t.i) + { + } + template + valptridx_t(const magic_constant &) : + p(static_cast(v) < get_array().size() ? &get_array()[v] : NULL), i(v) + { + } + template + valptridx_t(A &a, pointer_type t, index_type s) : + p(t), i(s) + { + check_null_pointer(); + check_index_match(a); + check_index_range(a); + } + valptridx_t(pointer_type t) : + p(t), i(t-get_array()) + { + check_null_pointer(); + auto &a = get_array(); + check_index_match(a); + check_index_range(a); + } + valptridx_t(index_type s) : + p(&get_array()[s]), i(s) + { + check_index_range(get_array()); + } +protected: + void check_null_pointer() const + { + DXX_VALPTRIDX_STATIC_CHECK(p, p, dxx_trap_constant_null_pointer, "NULL pointer used"); + if (!p) + throw null_pointer_exception("NULL pointer constructor"); + } + template + void check_index_match(A &a) + { + if (&a[i] != p) + throw index_mismatch_exception("pointer/index mismatch"); + } + template + void check_index_range(A &a) const + { + DXX_VALPTRIDX_STATIC_CHECK(i, static_cast(i) < a.size(), dxx_trap_constant_invalid_index, "invalid index used in array subscript"); + if (!(static_cast(i) < a.size())) + throw index_range_exception("index exceeds range"); + } + pointer_type p; + index_type i; + static decltype(get_global_array(pointer_type())) get_array() + { + return get_global_array(pointer_type()); + } +}; + +#define _DEFINE_VALPTRIDX_SUBTYPE_USERTYPE(N,P,I,A,name,Pconst) \ + static inline decltype(A) Pconst &get_global_array(P Pconst*) { return A; } \ + \ + struct name : valptridx_t

{ \ + name() = delete; \ + DXX_INHERIT_CONSTRUCTORS(name, valptridx_t

); \ }; \ \ - _DEFINE_VALPTRIDX_SUBTYPE_USERTYPES(N,P); \ + static inline name N(name::pointer_type o, name::index_type i) { \ + return {A, o, i}; \ + } \ \ - static inline N##_t N(N##_t::pointer_type o, N##_t::index_type i) { return N##_t(o, i); } \ - static inline c##N##_t N(c##N##_t::pointer_type o, c##N##_t::index_type i) { return c##N##_t(o, i); } \ + +#define DEFINE_VALPTRIDX_SUBTYPE(N,P,I,A) \ + _DEFINE_VALPTRIDX_SUBTYPE_USERTYPE(N,P,I,A,N##_t,); \ + _DEFINE_VALPTRIDX_SUBTYPE_USERTYPE(N,P,I,A,c##N##_t,const); \ diff --git a/common/main/object.h b/common/main/object.h index 5c5c1db6c..244134121 100644 --- a/common/main/object.h +++ b/common/main/object.h @@ -610,19 +610,27 @@ struct object_array_t : public array { return array_t::operator[](n); } + template + typename tt::enable_if::value, const_reference>::type operator[](T n) const + { + return array_t::operator[](n); + } template typename tt::enable_if::value, reference>::type operator[](T) const DXX_CXX11_EXPLICIT_DELETE; + object_array_t() = default; + object_array_t(const object_array_t &) = delete; + object_array_t &operator=(const object_array_t &) = delete; }; extern object_array_t Objects; DEFINE_VALPTRIDX_SUBTYPE(objptridx, object, int16_t, Objects); -static inline objptridx_t operator-(object *o, array& O) +static inline objptridx_t operator-(object *o, object_array_t &O) { - return objptridx_t(o, o - (&*O.begin())); + return objptridx(o, o - (&*O.begin())); } -objptridx_t operator-(objptridx_t, array &) DXX_CXX11_EXPLICIT_DELETE; +objptridx_t operator-(objptridx_t, object_array_t &) DXX_CXX11_EXPLICIT_DELETE; #endif /*