Skip to content
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
4 changes: 4 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 <unordered_map>

namespace stdcpp {
namespace test {
Expand All @@ -37,3 +38,6 @@ 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 std::unordered_map<int, char>;
template std::size_t stdcpp::test::cppSizeOf<std::unordered_map<int, char> >();
98 changes: 98 additions & 0 deletions source/stdcpp/Hashtable.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/**
* D header file for C++ Hashtable for unordered_map.
*
* 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: Emmanuel Nyarko
*
*/
module stdcpp.Hashtable;

import stdcpp.allocator;
import stdcpp.utility : pair;
import stdcpp.xutility : StdNamespace;

extern(C++, (StdNamespace)):

version (CppRuntime_Gcc)
{
/**
* structs for hashtable template arguments to get the right mangling
*/
struct hash(T)
{
}

struct equal_to(T = void)
{
}

extern(C++, "__detail") struct _Select1st
{
}

extern(C++, "__detail") struct _Mod_range_hashing
{
}

extern(C++, "__detail") struct _Default_ranged_hash
{
}

extern(C++, "__detail") struct _Prime_rehash_policy
{
}

extern(C++, "__detail") struct _Hashtable_traits(bool _Cache_hash_code, bool _Constant_iterators, bool _Unique_keys)
{
import stdcpp.type_traits : bool_constant;
alias __hash_cached = bool_constant!(_Cache_hash_code);
}

extern(C++, "__detail") struct _Hashtable_alloc(_NodeAlloc)
{
alias __node_base = _Hash_node_base;
alias __node_base_ptr = __node_base*;
alias __buckets_ptr = __node_base_ptr*;
}

extern(C++, "__detail") struct _Hash_node_base
{
_Hash_node_base* _M_next;
}

extern(C++, "__detail") struct _Hash_node(_Value, bool _Cache_hash_code)
{
_Hash_node_base __hb;
}

alias __umap_traits(bool _cache) = _Hashtable_traits!(_cache, false, true);

alias __umap_hashtable(_Key, _Tp, _Hash, _Pred, Alloc, _Tr = __umap_traits!(false)) = _Hashtable!(_Key, pair!(const(_Key), _Tp), Alloc, _Select1st, _Pred, _Hash,
_Mod_range_hashing, _Default_ranged_hash, _Prime_rehash_policy, _Tr );
extern(C++, class) struct _Hashtable(_Key, _Value, _Alloc, _ExtractKey, _Equal,
_Hash, _RangeHash, _Unused, _RehashPolicy, _Traits)
{
alias size_type = size_t;
alias __traits_type = _Traits;
alias __hash_cached = __traits_type.__hash_cached;
alias __node_type = _Hash_node!(_Value, __hash_cached.value);
alias __node_alloc_type = allocator_traits!(_Alloc).rebind_alloc!(__node_type);
alias __hashtable_alloc = _Hashtable_alloc!(__node_alloc_type);
alias __node_base = __hashtable_alloc.__node_base;
alias __buckets_ptr = __hashtable_alloc.__buckets_ptr;
alias __node_base_ptr = __hashtable_alloc.__node_base_ptr;

private:

__buckets_ptr _M_buckets;
size_type _M_bucket_count = 1;
__node_base _M_before_begin;
size_type _M_element_count = 0;
_RehashPolicy _M_rehash_policy;
__node_base_ptr _M_single_bucket;
void* _M_void;
}
}
40 changes: 40 additions & 0 deletions source/stdcpp/test/unordered_map.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*******************************************************************************

Tests for `std::unordered_map`

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

module stdcpp.test.unordered_map;

import stdcpp.unordered_map;
import stdcpp.test.base;

version (CppRuntime_Gcc)
{
unittest
{
assert(cppSizeOf!(unordered_map!(int, char)) == unordered_map!(int, char).sizeof);
}

unittest
{
auto p = unordered_map!(int, char)(5);
p.insert(1, 'a');
p.insert(2, 'b');
assert(p.size == 2);
p.insert(3, 'c');
assert(p.size == 3);
assert(p.bucket_count == 5);
assert(p.bucket_size(1) == 1); //return number of elements with index 0
assert(p.empty == 0);
auto q = unordered_map!(int, char)(p); // copy ctor
assert(q.size == 3);
q.insert(4, 'd');
assert(q.size == 4);
q.swap(p);
assert(q.size == 3); // after swap
assert(p.size == 4);
p.clear();
assert(p.empty == 1);
}
}
108 changes: 108 additions & 0 deletions source/stdcpp/unordered_map.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/**
* D header file for interaction with C++ std::unordered_map.
* See_Also:
* https://en.cppreference.com/w/cpp/container/unordered_map
* 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: Emmanuel Nyarko
*/

module stdcpp.unordered_map;

import stdcpp.allocator;
import stdcpp.Hashtable;
import stdcpp.utility : pair;
import stdcpp.xutility : StdNamespace;
extern(C++, (StdNamespace)):

extern(C++, class) struct unordered_map(Key, value, Hash = hash!Key, KeyEqual = equal_to!Key,
Alloc = allocator!(pair!(const(Key), value)))
{ ///
alias key_type = Key;
///
alias mapped_value = value;
///
alias size_type = size_t;
///
alias difference_type = ptrdiff_t;
///
alias key_equal = KeyEqual;
///
alias allocator_type = Alloc;
///
alias Pair = pair!(const(Key), value);
///
alias pointer = allocator_traits!(allocator_type).pointer;

alias _Hashtable = __umap_hashtable!(Key, value, Hash, KeyEqual, Alloc);

version(CppRuntime_Gcc)
{
///
this(size_type bucket_count)
{
allocator_type alloc_instance = allocator_type.init;
Hash hash_instance = Hash.init;
key_equal equal_instance = key_equal.init;
this(bucket_count, hash_instance, equal_instance, alloc_instance);
}
///
this(size_type bucket_count, const ref allocator_type);
///
this(const ref unordered_map __a)
{
allocator_type alloc_instance = allocator_type.init;
this(__a, alloc_instance);
}

//only bucket_count is non-default, rest are default. called from 'extern(D) this(size_type __x)'
this(size_type bucket_count, const ref Hash hash, const ref key_equal equal, const ref allocator_type __x);

this(const ref unordered_map __x, const ref allocator_type __a);

pair!(pointer, bool) insert(const ref Pair item);

///capacity
bool empty() const;
///
size_t size() const;
///
size_t max_size() const;

///Modifiers
void clear();
///
extern(D) pair!(pointer, bool) insert(const key_type key, value val)
{
Pair item = {key, val};
return insert(item);
}
///
void swap(ref unordered_map other) nothrow;

///bucket interface
size_type bucket_count() const;
///
size_type bucket_size(size_type n) const;


///Hash policy
float load_factor() const;
///
void max_load_factor(float ml);
///
float max_load_factor() const;
///
void rehash(size_type count);
///
void reserve(size_type count);

private _Hashtable _M_h;
}
else version(CppRuntime_Clang)
{
static assert(0, "CpppRuntime not yet supported");
}
}