Fold valptridx_t features into template
This commit is contained in:
parent
dd70a3f03d
commit
082bb43ede
|
@ -8,101 +8,134 @@
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include "dxxsconf.h"
|
#include "dxxsconf.h"
|
||||||
|
#include "compiler-type_traits.h"
|
||||||
/*
|
|
||||||
* A data type for passing both a pointer and its offset in an
|
|
||||||
* agreed-upon array. Useful for Segments, Objects.
|
|
||||||
*/
|
|
||||||
template <typename T, typename I>
|
|
||||||
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 <typename T> \
|
|
||||||
struct N##_template_t : public valptridx_t<T, I> \
|
|
||||||
|
|
||||||
#define _DEFINE_VALPTRIDX_SUBTYPE_TYPEDEFS(I) \
|
|
||||||
typedef valptridx_t<T, I> 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<P>); \
|
|
||||||
_DEFINE_VALPTRIDX_SUBTYPE_USERTYPE(c##N##_t, N##_template_t<P const>); \
|
|
||||||
|
|
||||||
#ifdef DXX_HAVE_BUILTIN_CONSTANT_P
|
#ifdef DXX_HAVE_BUILTIN_CONSTANT_P
|
||||||
#define DXX_VALPTRIDX_STATIC_CHECK(I,E,F,S) \
|
#define DXX_VALPTRIDX_STATIC_CHECK(I,E,F,S) \
|
||||||
if (dxx_builtin_constant_p(I) && !(E)) { \
|
if (dxx_builtin_constant_p(I) && !(E)) \
|
||||||
void F() __attribute_error(S); \
|
DXX_ALWAYS_ERROR_FUNCTION(F,S)
|
||||||
F(); \
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
#define DXX_VALPTRIDX_STATIC_CHECK(I,E,F,S) \
|
#define DXX_VALPTRIDX_STATIC_CHECK(I,E,F,S) \
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DEFINE_VALPTRIDX_SUBTYPE(N,P,I,A) \
|
template <typename T>
|
||||||
_DEFINE_VALPTRIDX_SUBTYPE_HEADER(N,I) \
|
void get_global_array(T *);
|
||||||
{ \
|
|
||||||
_DEFINE_VALPTRIDX_SUBTYPE_TYPEDEFS(I) \
|
/*
|
||||||
_DEFINE_VALPTRIDX_SUBTYPE_CTOR2(N,A) \
|
* A data type for passing both a pointer and its offset in an
|
||||||
N##_template_t(pointer_type t) : \
|
* agreed-upon array. Useful for Segments, Objects.
|
||||||
base_type(t, t-A) \
|
*/
|
||||||
{ \
|
template <typename T, typename I, template <I> class magic_constant>
|
||||||
DXX_VALPTRIDX_STATIC_CHECK(t, t, dxx_trap_constant_null_pointer, "NULL pointer used"); \
|
class valptridx_t
|
||||||
if (!t) \
|
{
|
||||||
throw std::logic_error("NULL pointer explicit constructor"); \
|
typedef valptridx_t<T, I, magic_constant> this_type;
|
||||||
if (&A[this->i] != t) \
|
public:
|
||||||
throw std::logic_error("unaligned pointer"); \
|
struct null_pointer_exception : std::logic_error {
|
||||||
} \
|
null_pointer_exception(const char *s) : std::logic_error(s) {}
|
||||||
N##_template_t(index_type s) : \
|
};
|
||||||
base_type(&A[s], s) \
|
struct index_mismatch_exception : std::logic_error {
|
||||||
{ \
|
index_mismatch_exception(const char *s) : std::logic_error(s) {}
|
||||||
DXX_VALPTRIDX_STATIC_CHECK(s, static_cast<std::size_t>(s) < A.size(), dxx_trap_constant_invalid_index, "invalid index used in array subscript"); \
|
};
|
||||||
if (!(static_cast<std::size_t>(s) < A.size())) \
|
struct index_range_exception : std::out_of_range {
|
||||||
throw std::out_of_range("index exceeds " #N " range"); \
|
index_range_exception(const char *s) : std::out_of_range(s) {}
|
||||||
} \
|
};
|
||||||
template <index_type i> \
|
typedef T *pointer_type;
|
||||||
N##_template_t(const P##_magic_constant_t<i> &) : \
|
typedef I index_type;
|
||||||
base_type(static_cast<std::size_t>(i) < A.size() ? &A[i] : NULL, i) \
|
pointer_type operator->() const { return p; }
|
||||||
{ \
|
operator pointer_type() const { return p; }
|
||||||
} \
|
operator const index_type&() const { return i; }
|
||||||
|
template <index_type v>
|
||||||
|
bool operator==(const magic_constant<v> &) 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 <typename R>
|
||||||
|
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 U>
|
||||||
|
typename tt::enable_if<!tt::is_base_of<this_type, U>::value, bool>::type operator==(U) const = delete;
|
||||||
|
valptridx_t() = delete;
|
||||||
|
valptridx_t(const valptridx_t<typename tt::remove_const<T>::type, I, magic_constant> &t) :
|
||||||
|
p(t.p), i(t.i)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
template <index_type v>
|
||||||
|
valptridx_t(const magic_constant<v> &) :
|
||||||
|
p(static_cast<std::size_t>(v) < get_array().size() ? &get_array()[v] : NULL), i(v)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
template <typename A>
|
||||||
|
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 <typename A>
|
||||||
|
void check_index_match(A &a)
|
||||||
|
{
|
||||||
|
if (&a[i] != p)
|
||||||
|
throw index_mismatch_exception("pointer/index mismatch");
|
||||||
|
}
|
||||||
|
template <typename A>
|
||||||
|
void check_index_range(A &a) const
|
||||||
|
{
|
||||||
|
DXX_VALPTRIDX_STATIC_CHECK(i, static_cast<std::size_t>(i) < a.size(), dxx_trap_constant_invalid_index, "invalid index used in array subscript");
|
||||||
|
if (!(static_cast<std::size_t>(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<P Pconst, I, P##_magic_constant_t> { \
|
||||||
|
name() = delete; \
|
||||||
|
DXX_INHERIT_CONSTRUCTORS(name, valptridx_t<P Pconst, I, P##_magic_constant_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); \
|
||||||
|
|
||||||
|
|
|
@ -610,19 +610,27 @@ struct object_array_t : public array<object, MAX_OBJECTS>
|
||||||
{
|
{
|
||||||
return array_t::operator[](n);
|
return array_t::operator[](n);
|
||||||
}
|
}
|
||||||
|
template <typename T>
|
||||||
|
typename tt::enable_if<tt::is_integral<T>::value, const_reference>::type operator[](T n) const
|
||||||
|
{
|
||||||
|
return array_t::operator[](n);
|
||||||
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename tt::enable_if<!tt::is_integral<T>::value, reference>::type operator[](T) const DXX_CXX11_EXPLICIT_DELETE;
|
typename tt::enable_if<!tt::is_integral<T>::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;
|
extern object_array_t Objects;
|
||||||
|
|
||||||
DEFINE_VALPTRIDX_SUBTYPE(objptridx, object, int16_t, Objects);
|
DEFINE_VALPTRIDX_SUBTYPE(objptridx, object, int16_t, Objects);
|
||||||
|
|
||||||
static inline objptridx_t operator-(object *o, array<object, MAX_OBJECTS>& 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<object, MAX_OBJECTS> &) DXX_CXX11_EXPLICIT_DELETE;
|
objptridx_t operator-(objptridx_t, object_array_t &) DXX_CXX11_EXPLICIT_DELETE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue