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

Commit

Permalink
Merge pull request #2286 from TurkeyMan/std_array
Browse files Browse the repository at this point in the history
Added std::array<>
  • Loading branch information
andralex authored Nov 8, 2018
2 parents 54051c8 + 62e69f0 commit 1bbbc9c
Show file tree
Hide file tree
Showing 15 changed files with 356 additions and 4 deletions.
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 \
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");
}
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)
{
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; } }
///
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;
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;
}
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;
}
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

0 comments on commit 1bbbc9c

Please sign in to comment.