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
12module core.stdcpp.array;
13
14import core.stdcpp.xutility : StdNamespace;
15
16// hacks to support DMD on Win32
17version (CppRuntime_Microsoft)
18{
19    version = CppRuntime_Windows; // use the MS runtime ABI for win32
20}
21else 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
27extern(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 */
34extern(C++, class) struct array(T, size_t N)
35{
36extern(D):
37pragma(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
59pure 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}
134