1 /**
2  * D header file for interaction with C++ std::array.
3  *
4  * Copyright: Copyright (c) 2018 D Language Foundation
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 import core.stdcpp.xutility : StdNamespace;
15 
16 // hacks to support DMD on Win32
17 version (CppRuntime_Microsoft)
18 {
19     version = CppRuntime_Windows; // use the MS runtime ABI for win32
20 }
21 else version (CppRuntime_DigitalMars)
22 {
23     version = CppRuntime_Windows; // use the MS runtime ABI for win32
24     pragma(msg, "std::array not supported by DMC");
25 }
26 
27 extern(C++, (StdNamespace)):
28 
29 /**
30  * D language counterpart to C++ std::array.
31  *
32  * C++ reference: $(LINK2 https://en.cppreference.com/w/cpp/container/array)
33  */
34 extern(C++, class) struct array(T, size_t N)
35 {
36 extern(D):
37 pragma(inline, true):
38 
39     ///
40     alias size_type = size_t;
41     ///
42     alias difference_type = ptrdiff_t;
43     ///
44     alias value_type = T;
45     ///
46     alias pointer = T*;
47     ///
48     alias const_pointer = const(T)*;
49 
50     ///
51     alias as_array this;
52 
53     /// Variadic constructor
54     this(T[N] args ...)                                 { this[] = args[]; }
55 
56     ///
57     void fill()(auto ref const(T) value)                { this[] = value; }
58 
59 pure nothrow @nogc:
60     ///
61     size_type size() const @safe                        { return N; }
62     ///
63     alias length = size;
64     ///
65     alias opDollar = length;
66     ///
67     size_type max_size() const @safe                    { return N; }
68     ///
69     bool empty() const @safe                            { return N == 0; }
70 
71     ///
72     ref inout(T) front() inout @safe                    { static if (N > 0) { return this[0]; } else { return as_array()[][0]; /* HACK: force OOB */ } }
73     ///
74     ref inout(T) back() inout @safe                     { static if (N > 0) { return this[N-1]; } else { return as_array()[][0]; /* HACK: force OOB */ } }
75 
76     version (CppRuntime_Windows)
77     {
78         ///
79         inout(T)* data() inout @safe                    { return &_Elems[0]; }
80         ///
81         ref inout(T)[N] as_array() inout @safe          { return _Elems[0 .. N]; }
82         ///
83         ref inout(T) at(size_type i) inout @safe        { return _Elems[0 .. N][i]; }
84 
85     private:
86         T[N ? N : 1] _Elems;
87     }
88     else version (CppRuntime_Gcc)
89     {
90         ///
91         inout(T)* data() inout @safe                    { static if (N > 0) { return &_M_elems[0]; } else { return null; } }
92         ///
93         ref inout(T)[N] as_array() inout @trusted       { return data()[0 .. N]; }
94         ///
95         ref inout(T) at(size_type i) inout @trusted     { return data()[0 .. N][i]; }
96 
97     private:
98         static if (N > 0)
99         {
100             T[N] _M_elems;
101         }
102         else
103         {
104             struct _Placeholder {}
105             _Placeholder _M_placeholder;
106         }
107     }
108     else version (CppRuntime_Clang)
109     {
110         ///
111         inout(T)* data() inout @trusted                 { static if (N > 0) { return &__elems_[0]; } else { return cast(inout(T)*)__elems_.ptr; } }
112         ///
113         ref inout(T)[N] as_array() inout @trusted       { return data()[0 .. N]; }
114         ///
115         ref inout(T) at(size_type i) inout @trusted     { return data()[0 .. N][i]; }
116 
117     private:
118         static if (N > 0)
119         {
120             T[N] __elems_;
121         }
122         else
123         {
124             struct _ArrayInStructT { T[1] __data_; }
125             align(_ArrayInStructT.alignof)
126             byte[_ArrayInStructT.sizeof] __elems_ = void;
127         }
128     }
129     else
130     {
131         static assert(false, "C++ runtime not supported");
132     }
133 }