#pragma once #include #include #include #include #include "exception.h" namespace MosesTraining { namespace Syntax { // Stores a set of elements of type T, each of which is allocated an integral // ID of type I. IDs are contiguous starting at 0. Individual elements cannot // be removed once inserted (but the whole set can be cleared). template class NumberedSet { private: typedef boost::unordered_map ElementToIdMap; typedef std::vector IdToElementMap; public: typedef I IdType; typedef typename IdToElementMap::const_iterator const_iterator; NumberedSet() {} const_iterator begin() const { return id_to_element_.begin(); } const_iterator end() const { return id_to_element_.end(); } // Static value static I NullId() { return std::numeric_limits::max(); } bool IsEmpty() const { return id_to_element_.empty(); } size_t Size() const { return id_to_element_.size(); } // Insert the given object and return its ID. I Insert(const T &); // Look up the given object and return its ID. I Lookup(const T &) const; // Look up the given object using an alternative key type (this is useful if, // for example, T is std::string and you want to look up the object using a // StringPiece). template I Lookup(const CompatibleKey &, const CompatibleHash &, const CompatiblePredicate &) const; // Lookup the object with the given ID. const T &Lookup(I) const; void Clear(); private: ElementToIdMap element_to_id_; IdToElementMap id_to_element_; }; template I NumberedSet::Lookup(const T &s) const { typename ElementToIdMap::const_iterator p = element_to_id_.find(s); return (p == element_to_id_.end()) ? NullId() : p->second; } template template I NumberedSet::Lookup(const CompatibleKey &key, const CompatibleHash &hash, const CompatiblePredicate &pred) const { typename ElementToIdMap::const_iterator p = element_to_id_.find(key, hash, pred); return (p == element_to_id_.end()) ? NullId() : p->second; } template const T &NumberedSet::Lookup(I id) const { // FIXME Need to check id is > 0 iff I is a signed type. //if (id < 0 || id >= id_to_element_.size()) { if (id >= id_to_element_.size()) { std::ostringstream msg; msg << "Value not found: " << id; throw Exception(msg.str()); } return *(id_to_element_[id]); } template I NumberedSet::Insert(const T &x) { std::pair value(x, id_to_element_.size()); std::pair result = element_to_id_.insert(value); if (result.second) { // x is a new element. id_to_element_.push_back(&result.first->first); } return result.first->second; } template void NumberedSet::Clear() { element_to_id_.clear(); id_to_element_.clear(); } } // namespace Syntax } // namespace MosesTraining