|
| 1 | +/** |
| 2 | + * D header file for interaction with C++ std::array. |
| 3 | + * |
| 4 | + * Copyright: Manu Evans 2014 - 2018. |
| 5 | + * License: Distributed under the |
| 6 | + * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). |
| 7 | + * (See accompanying file LICENSE) |
| 8 | + * Authors: Manu Evans |
| 9 | + * Source: $(DRUNTIMESRC core/stdcpp/array.d) |
| 10 | + */ |
| 11 | + |
| 12 | +module core.stdcpp.array; |
| 13 | + |
| 14 | +/////////////////////////////////////////////////////////////////////////////// |
| 15 | +// std::array declaration. |
| 16 | +// |
| 17 | +// - no iterators |
| 18 | +/////////////////////////////////////////////////////////////////////////////// |
| 19 | + |
| 20 | +import stdcpp.allocator; |
| 21 | + |
| 22 | +alias array = std.array; |
| 23 | + |
| 24 | +extern(C++, std): |
| 25 | + |
| 26 | +extern(C++, class) struct array(T, size_t N) |
| 27 | +{ |
| 28 | + alias size_type = size_t; |
| 29 | + alias difference_type = ptrdiff_t; |
| 30 | + alias value_type = T; |
| 31 | + alias reference = ref T; |
| 32 | + alias const_reference = ref const(T); |
| 33 | + alias pointer = T*; |
| 34 | + alias const_pointer = const(T)*; |
| 35 | +// alias iterator = pointer; |
| 36 | +// alias const_iterator = const_pointer; |
| 37 | +// alias reverse_iterator |
| 38 | +// alias const_reverse_iterator |
| 39 | + |
| 40 | + // Iterators |
| 41 | +// iterator begin() @trusted @nogc; |
| 42 | +// const_iterator begin() const @trusted @nogc; |
| 43 | +// const_iterator cbegin() const @trusted @nogc; |
| 44 | +// iterator end() @trusted @nogc; |
| 45 | +// const_iterator end() const @trusted @nogc; |
| 46 | +// const_iterator cend() const @trusted @nogc; |
| 47 | + |
| 48 | + // no reverse iterator for now. |
| 49 | + |
| 50 | + alias as_array this; |
| 51 | + |
| 52 | + extern(D) size_type size() const nothrow @safe @nogc { return N; } |
| 53 | + extern(D) size_type max_size() const nothrow @safe @nogc { return N; } |
| 54 | + extern(D) bool empty() const nothrow @safe @nogc { return N > 0; } |
| 55 | + |
| 56 | + // Element access |
| 57 | + extern(D) reference front() @safe @nogc { return as_array()[0]; } |
| 58 | + extern(D) const_reference front() const @safe @nogc { return as_array()[0]; } |
| 59 | + extern(D) reference back() @safe @nogc { return as_array()[N == 0 ? 0 : N-1]; } |
| 60 | + extern(D) const_reference back() const @safe @nogc { return as_array()[N == 0 ? 0 : N-1]; } |
| 61 | + |
| 62 | + extern(D) void fill(ref const(T) value) @safe @nogc { foreach (ref T v; as_array()) v = value; } |
| 63 | + |
| 64 | + // D helpers |
| 65 | + extern(D) T[] opSlice() nothrow @safe @nogc { return as_array(); } |
| 66 | + extern(D) const(T)[] opSlice() const nothrow @safe @nogc { return as_array(); } |
| 67 | + extern(D) T[] opSlice(size_type start, size_type end) @safe { assert(start <= end && end <= N, "Index out of bounds"); return as_array()[start .. end]; } |
| 68 | + extern(D) const(T)[] opSlice(size_type start, size_type end) const @safe { assert(start <= end && end <= N, "Index out of bounds"); return as_array()[start .. end]; } |
| 69 | + extern(D) size_type opDollar(size_t pos)() const nothrow @safe @nogc { static assert(pos == 0, "std::vector is one-dimensional"); return N; } |
| 70 | + |
| 71 | + // support all the assignment variants |
| 72 | + extern(D) void opSliceAssign(T value) { opSlice()[] = value; } |
| 73 | + extern(D) void opSliceAssign(T value, size_type i, size_type j) { opSlice(i, j)[] = value; } |
| 74 | + extern(D) void opSliceUnary(string op)() if (op == "++" || op == "--") { mixin(op ~ "opSlice()[];"); } |
| 75 | + extern(D) void opSliceUnary(string op)(size_type i, size_type j) if (op == "++" || op == "--") { mixin(op ~ "opSlice(i, j)[];"); } |
| 76 | + extern(D) void opSliceOpAssign(string op)(T value) { mixin("opSlice()[] " ~ op ~ "= value;"); } |
| 77 | + extern(D) void opSliceOpAssign(string op)(T value, size_type i, size_type j) { mixin("opSlice(i, j)[] " ~ op ~ "= value;"); } |
| 78 | + |
| 79 | +private: |
| 80 | + version(CRuntime_Microsoft) |
| 81 | + { |
| 82 | + import core.stdcpp.utility : _Xout_of_range; |
| 83 | + |
| 84 | + T[N ? N : 1] _Elems; |
| 85 | + |
| 86 | + void _Xran() const @trusted @nogc { _Xout_of_range("invalid array<T, N> subscript"); } |
| 87 | + |
| 88 | + public: |
| 89 | + // perf will be greatly improved by inlining the primitive access functions |
| 90 | + extern(D) T* data() nothrow @safe @nogc { return &_Elems[0]; } |
| 91 | + extern(D) const(T)* data() const nothrow @safe @nogc { return &_Elems[0]; } |
| 92 | + |
| 93 | + extern(D) ref T opIndex(size_type i) nothrow @safe @nogc { return _Elems[0 .. N][i]; } |
| 94 | + extern(D) ref const(T) opIndex(size_type i) const nothrow @safe @nogc { return _Elems[0 .. N][i]; } |
| 95 | + extern(D) ref T at(size_type i) nothrow @trusted @nogc { static if (N > 0) { if (N <= i) _Xran(); return _Elems.ptr[i]; } else { _Xran(); } } |
| 96 | + extern(D) ref const(T) at(size_type i) const nothrow @trusted @nogc { static if (N > 0) { if (N <= i) _Xran(); return _Elems.ptr[i]; } else { _Xran(); } } |
| 97 | + |
| 98 | + extern(D) T[] as_array() nothrow @safe @nogc { return _Elems[0 .. N]; } |
| 99 | + extern(D) const(T)[] as_array() const nothrow @safe @nogc { return _Elems[0 .. N]; } |
| 100 | + } |
| 101 | + else version(CRuntime_Glibc) |
| 102 | + { |
| 103 | + static if (N > 0) |
| 104 | + { |
| 105 | + T[N] _M_elems; |
| 106 | + } |
| 107 | + else |
| 108 | + { |
| 109 | + struct _Placeholder {} |
| 110 | + _Placeholder _M_placeholder; |
| 111 | + } |
| 112 | + |
| 113 | + public: |
| 114 | + import core.exception : RangeError; |
| 115 | + |
| 116 | + // perf will be greatly improved by inlining the primitive access functions |
| 117 | + extern(D) T* data() nothrow @safe @nogc { static if (N > 0) { return &_M_elems[0]; } else { return null; } } |
| 118 | + extern(D) const(T)* data() const nothrow @safe @nogc { static if (N > 0) { return &_M_elems[0]; } else { return null; } } |
| 119 | + |
| 120 | + extern(D) ref T opIndex(size_type i) nothrow @nogc { static if (N > 0) { return _M_elems[i]; } else { return (cast(T[])null)[i]; } } |
| 121 | + extern(D) ref const(T) opIndex(size_type i) const nothrow @nogc { static if (N > 0) { return _M_elems[i]; } else { return (cast(T[])null)[i]; } } |
| 122 | + extern(D) ref T at(size_type i) @trusted { if (i >= N) throw new RangeError("Index out of range"); return _M_elems.ptr[i]; } |
| 123 | + extern(D) ref const(T) at(size_type i) const @trusted { if (i >= N) throw new RangeError("Index out of range"); return _M_elems.ptr[i]; } |
| 124 | + |
| 125 | + alias as_array this; |
| 126 | + extern(D) T[] as_array() nothrow @safe @nogc { static if (N > 0) { return _M_elems[]; } else { return null; } } |
| 127 | + extern(D) const(T)[] as_array() const nothrow @safe @nogc { static if (N > 0) { return _M_elems[]; } else { return null; } } |
| 128 | + } |
| 129 | + else |
| 130 | + { |
| 131 | + static assert(false, "C++ runtime not supported"); |
| 132 | + } |
| 133 | +} |
0 commit comments