Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Added std::array<> #2286

Merged
merged 12 commits into from
Nov 8, 2018
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
root = true

[*.{c,h,d,di,dd}]
[*.{c,cpp,h,d,di,dd}]
insert_final_newline = true
indent_style = space
indent_size = 4
Expand Down
3 changes: 3 additions & 0 deletions changelog/array.dd
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Added `core.stdcpp.array`.

Added `core.stdcpp.array`, which links against C++ `std::array`
4 changes: 3 additions & 1 deletion mak/COPY
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ COPY=\
$(IMPDIR)\core\stdc\wchar_.d \
$(IMPDIR)\core\stdc\wctype.d \
\
$(IMPDIR)\core\stdcpp\typeinfo.d \
$(IMPDIR)\core\stdcpp\array.d \
$(IMPDIR)\core\stdcpp\exception.d \
$(IMPDIR)\core\stdcpp\typeinfo.d \
$(IMPDIR)\core\stdcpp\xutility.d \
\
$(IMPDIR)\core\sys\darwin\execinfo.d \
$(IMPDIR)\core\sys\darwin\pthread.d \
Expand Down
1 change: 1 addition & 0 deletions mak/DOCS
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ DOCS=\
$(DOCDIR)\core_stdc_wchar_.html \
$(DOCDIR)\core_stdc_wctype.html \
\
$(DOCDIR)\core_stdcpp_array.html \
$(DOCDIR)\core_stdcpp_exception.html \
$(DOCDIR)\core_stdcpp_typeinfo.html \
\
Expand Down
3 changes: 3 additions & 0 deletions mak/SRCS
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ SRCS=\
src\core\stdc\time.d \
src\core\stdc\wchar_.d \
\
src\core\stdcpp\array.d \
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why aren't any other the other existing files in here?

src\core\stdcpp\xutility.d \
\
src\core\sync\barrier.d \
src\core\sync\condition.d \
src\core\sync\config.d \
Expand Down
6 changes: 6 additions & 0 deletions mak/WINDOWS
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,15 @@ $(IMPDIR)\core\stdc\wctype.d : src\core\stdc\wctype.d
$(IMPDIR)\core\stdcpp\exception.d : src\core\stdcpp\exception.d
copy $** $@

$(IMPDIR)\core\stdcpp\array.d : src\core\stdcpp\array.d
copy $** $@

$(IMPDIR)\core\stdcpp\typeinfo.d : src\core\stdcpp\typeinfo.d
copy $** $@

$(IMPDIR)\core\stdcpp\xutility.d : src\core\stdcpp\xutility.d
copy $** $@

$(IMPDIR)\core\sys\darwin\execinfo.d : src\core\sys\darwin\execinfo.d
copy $** $@

Expand Down
2 changes: 1 addition & 1 deletion posix.mak
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ HAS_ADDITIONAL_TESTS:=$(shell test -d test && echo 1)
ifeq ($(HAS_ADDITIONAL_TESTS),1)
ADDITIONAL_TESTS:=test/init_fini test/exceptions test/coverage test/profile test/cycles test/allocations test/typeinfo \
test/aa test/hash \
test/thread test/unittest test/imports test/betterc
test/thread test/unittest test/imports test/betterc test/stdcpp
ADDITIONAL_TESTS+=$(if $(SHARED),test/shared,)
endif

Expand Down
145 changes: 145 additions & 0 deletions src/core/stdcpp/array.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/**
* D header file for interaction with C++ std::array.
*
* Copyright: Copyright (c) 2018 D Language Foundation
* License: Distributed under the
* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
* (See accompanying file LICENSE)
* Authors: Manu Evans
* Source: $(DRUNTIMESRC core/stdcpp/array.d)
*/

module core.stdcpp.array;

// hacks to support DMD on Win32
version (CppRuntime_Microsoft)
{
version = CppRuntime_Windows; // use the MS runtime ABI for win32
}
else version (CppRuntime_DigitalMars)
{
version = CppRuntime_Windows; // use the MS runtime ABI for win32
pragma(msg, "std::array not supported by DMC");
TurkeyMan marked this conversation as resolved.
Show resolved Hide resolved
}
version (CppRuntime_Clang)
{
private alias AliasSeq(Args...) = Args;
private enum StdNamespace = AliasSeq!("std", "__1");
}
else
{
private enum StdNamespace = "std";
}

extern(C++, (StdNamespace)):

/**
* D language counterpart to C++ std::array.
*
* C++ reference: $(LINK2 https://en.cppreference.com/w/cpp/container/array)
*/
extern(C++, class) struct array(T, size_t N)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation

{
extern(D):
pragma(inline, true):

///
alias size_type = size_t;
///
alias difference_type = ptrdiff_t;
///
alias value_type = T;
///
alias pointer = T*;
///
alias const_pointer = const(T)*;

///
alias as_array this;

/// Variadic constructor
this(T[N] args ...) { this[] = args[]; }

///
size_type size() const nothrow @safe @nogc { return N; }
///
alias length = size;
///
alias opDollar = length;
///
size_type max_size() const nothrow @safe @nogc { return N; }
///
bool empty() const nothrow @safe @nogc { return N == 0; }

///
ref inout(T) front() inout nothrow @safe @nogc { static if (N > 0) { return this[0]; } else { return as_array()[][0]; /* HACK: force OOB */ } }
///
ref inout(T) back() inout nothrow @safe @nogc { static if (N > 0) { return this[N-1]; } else { return as_array()[][0]; /* HACK: force OOB */ } }

///
void fill()(auto ref const(T) value) { this[] = value; }

version (CppRuntime_Windows)
{
///
inout(T)* data() inout nothrow @safe @nogc { return &_Elems[0]; }
///
ref inout(T)[N] as_array() const inout @safe @nogc { return _Elems[0 .. N]; }
///
ref inout(T) at(size_type i) inout nothrow @safe @nogc { return _Elems[0 .. N][i]; }

version (CppRuntime_Microsoft)
{
import core.stdcpp.xutility : MSVCLinkDirectives;
mixin MSVCLinkDirectives!false;
}

private:
T[N ? N : 1] _Elems;
}
else version (CppRuntime_Gcc)
{
///
inout(T)* data() inout nothrow @safe @nogc { static if (N > 0) { return &_M_elems[0]; } else { return null; } }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since those files are not automatic porting but quite curated translation, please follow the D style

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole file is inline one-liners at the same indentation level.
I think @WalterBright addresses this issue in his lecture: https://youtu.be/lbp6vwdnE0k?t=3672

///
ref inout(T)[N] as_array() inout nothrow @trusted @nogc { return data()[0 .. N]; }
///
ref inout(T) at(size_type i) inout nothrow @trusted @nogc { return data()[0 .. N][i]; }

private:
static if (N > 0)
{
T[N] _M_elems;
}
else
{
struct _Placeholder {}
_Placeholder _M_placeholder;
}
}
else version (CppRuntime_Clang)
{
///
inout(T)* data() inout nothrow @trusted @nogc { static if (N > 0) { return &__elems_[0]; } else { return cast(inout(T)*)__elems_.ptr; } }
///
ref inout(T)[N] as_array() inout nothrow @trusted @nogc { return data()[0 .. N]; }
///
ref inout(T) at(size_type i) inout nothrow @trusted @nogc { return data()[0 .. N][i]; }

private:
static if (N > 0)
{
T[N] __elems_;
}
else
{
struct _ArrayInStructT { T[1] __data_; }
align(_ArrayInStructT.alignof)
byte[_ArrayInStructT.sizeof] __elems_ = void;
}
}
else
{
static assert(false, "C++ runtime not supported");
}
}
60 changes: 60 additions & 0 deletions src/core/stdcpp/xutility.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* D header file for interaction with Microsoft C++ <xutility>
*
* Copyright: Copyright (c) 2018 D Language Foundation
* License: Distributed under the
* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
* (See accompanying file LICENSE)
* Authors: Manu Evans
* Source: $(DRUNTIMESRC core/stdcpp/xutility.d)
*/

module core.stdcpp.xutility;

extern(C++, "std"):

version (CppRuntime_Microsoft)
{
// Client code can mixin the set of MSVC linker directives
mixin template MSVCLinkDirectives(bool failMismatch = false)
{
import core.stdcpp.xutility : __CXXLIB__;

static if (__CXXLIB__ == "libcmtd")
{
pragma(lib, "libcpmtd");
static if (failMismatch)
pragma(linkerDirective, "/FAILIFMISMATCH:RuntimeLibrary=MTd_StaticDebug");
}
else static if (__CXXLIB__ == "msvcrtd")
{
pragma(lib, "msvcprtd");
static if (failMismatch)
pragma(linkerDirective, "/FAILIFMISMATCH:RuntimeLibrary=MDd_DynamicDebug");
}
else static if (__CXXLIB__ == "libcmt")
{
pragma(lib, "libcpmt");
static if (failMismatch)
pragma(linkerDirective, "/FAILIFMISMATCH:RuntimeLibrary=MT_StaticRelease");
}
else static if (__CXXLIB__ == "msvcrt")
{
pragma(lib, "msvcprt");
static if (failMismatch)
pragma(linkerDirective, "/FAILIFMISMATCH:RuntimeLibrary=MD_DynamicRelease");
}
}

// convenient alias for the C++ std library name
enum __CXXLIB__ = __traits(getTargetInfo, "cppRuntimeLibrary");

package:
// these are all [[noreturn]]
void _Xbad() nothrow @trusted @nogc;
TurkeyMan marked this conversation as resolved.
Show resolved Hide resolved
void _Xinvalid_argument(const(char)* message) nothrow @trusted @nogc;
void _Xlength_error(const(char)* message) nothrow @trusted @nogc;
void _Xout_of_range(const(char)* message) nothrow @trusted @nogc;
void _Xoverflow_error(const(char)* message) nothrow @trusted @nogc;
void _Xruntime_error(const(char)* message) nothrow @trusted @nogc;
TurkeyMan marked this conversation as resolved.
Show resolved Hide resolved
}
4 changes: 4 additions & 0 deletions test/common.mak
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,7 @@ else
DFLAGS += -O -release
CFLAGS += -O3
endif
CXXFLAGS:=$(CFLAGS) -std=c++11
ifeq (osx,$(OS))
CXXFLAGS+=-stdlib=libc++
endif
29 changes: 29 additions & 0 deletions test/stdcpp/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
include ../common.mak

TESTS:=array

.PHONY: all clean

# osx32 does not link properly, nobody uses it anyway...
ifeq ($(OS)$(MODEL), osx32)

all:

clean:

else
all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS)))

$(ROOT)/%.done : $(ROOT)/%
@echo Testing $*
$(QUIET)$(TIMELIMIT)$(ROOT)/$* $(RUN_ARGS)
@touch $@

$(ROOT)/%: $(SRC)/%_test.d $(SRC)/%.cpp
mkdir -p $(dir $@)
$(QUIET)$(CXX) $(CXXFLAGS) -c -o $(ROOT)/$*_cpp.o $(SRC)/$*.cpp
$(QUIET)$(DMD) $(DFLAGS) -main -unittest -of$@ $< $(ROOT)/$*_cpp.o

clean:
rm -rf $(GENERATED)
endif
20 changes: 20 additions & 0 deletions test/stdcpp/src/array.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include <array>

std::array<int, 5> fromC_val(std::array<int, 5>);
std::array<int, 5>& fromC_ref(std::array<int, 5>&);

std::array<int, 5>& sumOfElements_ref(std::array<int, 5>& arr)
{
int r = 0;
for (size_t i = 0; i < arr.size(); ++i)
r += arr[i];
arr.fill(r);
return arr;
}

std::array<int, 5> sumOfElements_val(std::array<int, 5> arr)
{
int r = sumOfElements_ref(arr)[0] + fromC_ref(arr)[0] + fromC_val(arr)[0];
arr.fill(r);
return arr;
}
TurkeyMan marked this conversation as resolved.
Show resolved Hide resolved
62 changes: 62 additions & 0 deletions test/stdcpp/src/array_test.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import core.stdcpp.array;

extern (C++) int test_array()
{
array!(int, 5) arr;
arr[] = [0, 2, 3, 4, 5];
++arr.front;

assert(arr.size == 5);
assert(arr.length == 5);
assert(arr.max_size == 5);
assert(arr.empty == false);
assert(arr.front == 1);

assert(sumOfElements_val(arr)[0] == 160);
assert(sumOfElements_ref(arr)[0] == 15);

array!(int, 0) arr2;
assert(arr2.size == 0);
assert(arr2.length == 0);
assert(arr2.max_size == 0);
assert(arr2.empty == true);
assert(arr2[] == []);

return 0;
}


extern(C++):

// test the ABI for calls to C++
array!(int, 5) sumOfElements_val(array!(int, 5) arr);
ref array!(int, 5) sumOfElements_ref(return ref array!(int, 5) arr);

// test the ABI for calls from C++
array!(int, 5) fromC_val(array!(int, 5) arr)
{
assert(arr[] == [1, 2, 3, 4, 5]);
assert(arr.front == 1);
assert(arr.back == 5);
assert(arr.at(2) == 3);

arr.fill(2);

int r;
foreach (e; arr)
r += e;

assert(r == 10);

arr[] = r;
return arr;
}

ref array!(int, 5) fromC_ref(return ref array!(int, 5) arr)
{
int r;
foreach (e; arr)
r += e;
arr[] = r;
return arr;
}
Loading