RenderCore/Base/CKDictionary.h (46 lines of code) (raw):

/* * Copyright (c) 2014-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * */ #import <RenderCore/CKDefines.h> #if CK_NOT_SWIFT #pragma once #include <algorithm> #include <utility> #include <vector> #import <RenderCore/CKCollection.h> namespace CK { /** An associative container that stores a mapping from instances of \c Key to instances of \c Value . \c CK::Dictionary does not require keys to be hashable, only to be equatable. Both keys and values must be default constructible. Insertions take linear time. */ template <typename Key, typename Value> class Dictionary { using Storage = std::vector<std::pair<Key, Value>>; public: using value_type = typename Storage::value_type; using const_reference = typename Storage::const_reference; /** Initialises an empty dictionary. */ Dictionary() = default; /** Initialises a dictionary from a list of key-value pairs. Keys must be unique. */ Dictionary(std::initializer_list<value_type> kvs) : _elements{kvs} { #ifndef NDEBUG auto keys = std::vector<Key>{}; for (auto const &kv : kvs) { assert(!CK::Collection::contains(keys, kv.first) && "Keys must be unique"); keys.push_back(kv.first); } #endif } auto begin() & { return _elements.begin(); } auto end() & { return _elements.end(); } auto begin() const & { return _elements.cbegin(); } auto end() const & { return _elements.cend(); } auto empty() const { return _elements.empty(); } auto size() const { return _elements.size(); } /** Provides access to keys and values stored in the dictionary. \param key A key used to look up the value. \return A reference to an existing value, or, if the key was previously missing, a reference to just inserted default constructed value. */ auto operator [](const Key &key) -> Value & { auto const it = CK::find_if(_elements, [&key](const_reference kv) { return kv.first == key; }); if (it == _elements.end()) { _elements.emplace_back(key, Value{}); return _elements.back().second; } else { return it->second; } } private: Storage _elements; }; } #endif