Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

D std::map bindings using the wrapper method #22

Open
wants to merge 17 commits into
base: v1.x.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dub.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"$PACKAGE_DIR/extras/cxx-wrapper.sh test",
],
"preGenerateCommands-windows": [
"cl /c /Fo: $PACKAGE_DIR/extras/ $PACKAGE_DIR/extras/test.cpp",
"cl /c /I$PACKAGE_DIR/extras/AssociativeContainers/ /Fo: $PACKAGE_DIR/extras/ $PACKAGE_DIR/extras/test.cpp /std:c++20",
],
"sourceFiles-posix": [ "extras/test.o" ],
"sourceFiles-windows": [ "extras/test.obj" ]
Expand Down
43 changes: 43 additions & 0 deletions extras/AssociativeContainers/map.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*******************************************************************************

C++ map source file to generate symbols for D using the wrapper method

In order to make the symbols available, we call the functions from the map
instance so we can effectively use them in D

*******************************************************************************/

#include <map>

template <typename K, typename V>
class Map
{
void insertOrAssign(const K& key, const V& value)
{
this->map.insert_or_assign(key, value);
}

std::map<K, V> map;

public: // msvc mangles public and private static fields differently so need for public
static Map<K,V>* make() { return new Map<K, V>(); }

size_t size() { return this->map.size(); }

V& operator[] (K const& key) { return this->map[key]; }

V& at(K const& key) { return this->map.at(key); }

bool empty() const noexcept { return this->map.empty(); }

size_t max_size() const { return this->map.max_size(); }

void clear() noexcept { this->map.clear(); }

size_t count(K const& key ) const { return this->map.count(key); }

bool contains(K const& key ) const { return this->map.contains(key);}

void swap( Map* other) noexcept { this->map.swap(other->map); } // swap with the function parameter's map

};
2 changes: 1 addition & 1 deletion extras/cxx-wrapper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ fi

EXTRAS_DIR=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd)

$CXX -c ${EXTRAS_DIR}/$1.cpp -o ${EXTRAS_DIR}/$1.o
$CXX -c ${EXTRAS_DIR}/$1.cpp -o ${EXTRAS_DIR}/$1.o -I${EXTRAS_DIR}/AssociativeContainers/ --std=c++2a
3 changes: 3 additions & 0 deletions extras/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <string>
#include <vector>
#include <set>
#include "map.hpp"

namespace stdcpp {
namespace test {
Expand All @@ -37,3 +38,5 @@ template std::size_t stdcpp::test::cppSizeOf<std::vector<int> >();

template class std::set<int>;
template std::size_t stdcpp::test::cppSizeOf<std::set<int> >();

template class Map<int, char>;
10 changes: 6 additions & 4 deletions source/stdcpp/list.d
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,11 @@ extern(C++, class) struct list(Type, Allocator)
this.resize(n, item);
}

extern(D) void remove(const value_type item)
/* extern(D) size_type remove(const value_type item)
{
this.remove(item);
return this.remove(item);
}
*/

ref list opAssign(ref const list!Type other);

Expand Down Expand Up @@ -261,7 +262,7 @@ extern(C++, class) struct list(Type, Allocator)

void merge(U)(ref const list!Type other, U comp);

void remove(const ref value_type val);
// size_type remove(const ref value_type val);

void reverse() nothrow;

Expand Down Expand Up @@ -412,11 +413,12 @@ extern(C++, class) struct list(Type, Allocator)

this(size_type __n, ref const value_type value, ref const allocator!Type);

extern(D) this(size_type n, const value_type element)
/* extern(D) this(size_type n, const value_type element)
{
allocator!Type alloc_instance = allocator!(Type).init;
this(n, element, alloc_instance);
}
*/

this(ref const list!Type other, ref const allocator!Type);

Expand Down
63 changes: 63 additions & 0 deletions source/stdcpp/map.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* D bindings for std::map
* see_Also:
* https://en.cppreference.com/w/cpp/container/map
* Copyright: Copyright (c) 2023 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: Emmanuel Nyarko, Mathias Lang
*/
module stdcpp.map;

extern(C++, class):
struct Map(Key, Value)
{
///
extern(D) void opIndexAssign (const Key key, Value value)
{
this.insertOrAssign(key, value);
}
///
static Map* make();
///
private void insertOrAssign(const ref Key, const ref Value);
///
size_t size();
///
ref Value opIndex( ref const Key key);
///
ref Value opIndex(const Key key)
{
return this.opIndex(key); // handle rvalue-ref
}
///
ref Value at( ref const Key key);
///
extern(D) ref Value at(const Key key)
{
return this.at(key);
}
///
bool empty() const nothrow;
///
size_t max_size() const;
///
void clear() nothrow;
///
size_t count(ref const Key key) const;
///
extern(D) size_t count(const Key key) const
{
return this.count(key);
}
///
bool contains( ref const Key key) const;
///
extern(D) bool contains(const Key key) const
{
return this.contains(key);
}
///
void swap( Map* other) nothrow;
}
38 changes: 38 additions & 0 deletions source/stdcpp/test/map.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*******************************************************************************

Tests for `std::map`

*******************************************************************************/

module stdcpp.test.map;

import stdcpp.map;

unittest
{
auto mymap = Map!(int, char).make();
mymap.opIndexAssign(1, 'a');
assert(mymap.size == 1);
assert(mymap.opIndex(1) == 'a');
mymap.opIndex(2) = 'b';
mymap.opIndex(3) = 'c';
assert(mymap.contains(3) == 1); // returns true
assert(mymap.size == 3);
assert(mymap.empty == 0);
assert(mymap.at(2) == 'b');
assert(mymap.count(1) == 1);
mymap.clear();
assert(mymap.size == 0);
assert(mymap.empty == 1);
assert(mymap.count(1) == 0); // container cleared
/* utilities to use to test after a swap */
mymap.opIndex(2) = 'b';
mymap.opIndex(3) = 'c';

/* testing for swap*/
auto mymap2 = Map!(int, char).make();
mymap2.swap(mymap);
assert(mymap2.size == 2);
assert(mymap2.at(2) == 'b');
assert(mymap2.at(3) == 'c'); // swap works!
}
Loading