1 module nxt.container.bimap; 2 3 @safe pure: 4 5 /** Bidirectional map between key-and-values of type `X` and `Y` inspired by C++ 6 Boost Bimap (`boost::bimap`). Map-type defaults to a builtin associative 7 array (AA). 8 9 See_Also: http://www.boost.org/doc/libs/1_65_1/libs/bimap/doc/html/boost_bimap/one_minute_tutorial.html 10 */ 11 struct BiMap(X, Y, alias Map = Y[X]) { 12 @safe pure nothrow: 13 alias LeftMap = Map!(X, Y); 14 alias RightMap = Map!(Y, X); 15 16 /// Insert (`x`, `y`). 17 void insert(X x, Y y) { 18 pragma(inline, true); 19 _left[x] = y; 20 _right[y] = x; 21 } 22 23 /// Check if (`x`, `y`) is stored. 24 bool contains(scope const X x, 25 scope const Y y) const 26 { 27 version (LDC) pragma(inline, true); 28 /+ TODO: do this symmetric? +/ 29 if (const hitPtr = x in _left) 30 return *hitPtr == y; 31 return false; 32 } 33 34 /// Clear contents. 35 void clear() @trusted /+ TODO: ok for this to be `@trusted`? +/ 36 { 37 version (D_Coverage) {} else pragma(inline, true); 38 _left.clear(); 39 _right.clear(); 40 } 41 42 /// Check if empty. 43 bool empty() const @property @nogc => length == 0; 44 /// Get length. 45 size_t length() const @nogc => _left.length; 46 /// Access to left map must be non-mutating. 47 ref const(LeftMap) left() const @nogc => _left; 48 /// Access to right map must be non-mutating. 49 ref const(RightMap) right() const @nogc => _right; 50 private: 51 LeftMap _left; ///< Left map. 52 RightMap _right; ///< Right map. 53 } 54 55 /// test with builtin associative arrays 56 pure nothrow @safe unittest { 57 alias HashMap(Key, Value) = Value[Key]; 58 BiMap!(size_t, string, HashMap) bm; 59 60 bm.insert(42, "42"); 61 62 assert(bm.left.length == 1); 63 assert(bm.right.length == 1); 64 65 assert(bm.contains(42, "42")); 66 67 bm.clear(); 68 assert(bm.empty); 69 }