#pragma once
#include "../../common/specialized.hpp"
#include "../../common/compat.hpp"
namespace sprawl
{
template<typename A, typename B>
class MapIterator;
namespace collections
{
template< typename A, typename... B >
class HashMap;
namespace detail
{
template< typename A, typename B, size_t C, typename... D >
class HashMap_Impl;
template<typename ValueType, typename MostInheritedType, size_t index, typename... AdditionalAccessors>
class AccessorGroup_Impl;
template<typename ValueType, typename MostInheritedType, size_t index>
class AccessorGroup_Impl<ValueType, MostInheritedType, index>
{
public:
ValueType& Value()
{
return m_value;
}
ValueType const& Value() const
{
return m_value;
}
ValueType& operator*()
{
return m_value;
}
ValueType* operator->()
{
return &m_value;
}
ValueType const& operator*() const
{
return m_value;
}
ValueType const* operator->() const
{
return &m_value;
}
inline NullAccessor& Accessor(Specialized<index>)
{
static NullAccessor accessor;
return accessor;
}
inline NullAccessor const& Accessor(Specialized<index>) const
{
static NullAccessor accessor;
return accessor;
}
protected:
template< typename A, typename... B >
friend class sprawl::collections::HashMap;
template< typename A, typename B, size_t C, typename... D >
friend class sprawl::collections::detail::HashMap_Impl;
template<typename A, typename B>
friend class sprawl::MapIterator;
AccessorGroup_Impl(ValueType const& value)
: next(nullptr)
, prev(nullptr)
, m_value(value)
{
//
}
AccessorGroup_Impl(ValueType&& value)
: next(nullptr)
, prev(nullptr)
, m_value(std::move(value))
{
//
}
AccessorGroup_Impl(AccessorGroup_Impl const& other)
: next(nullptr)
, prev(nullptr)
, m_value(other.m_value)
{
//
}
inline MostInheritedType* Next(Specialized<index>)
{
return nullptr;
}
inline MostInheritedType* Prev(Specialized<index>)
{
return nullptr;
}
inline void SetNext(Specialized<index>, MostInheritedType*)
{
//
}
inline void SetPrev(Specialized<index>, MostInheritedType*)
{
//
}
inline size_t Idx(Specialized<index>)
{
return -1;
}
inline void SetIndex(Specialized<index>, size_t)
{
//
}
inline size_t GetHash(Specialized<index>)
{
return -1;
}
inline void SetHash(Specialized<index>, size_t)
{
//
}
MostInheritedType* next;
MostInheritedType* prev;
ValueType m_value;
};
template<typename ValueType, typename MostInheritedType, size_t index, typename AccessorType, typename... AdditionalAccessors>
class AccessorGroup_Impl<ValueType, MostInheritedType, index, AccessorType, AdditionalAccessors...> : public AccessorGroup_Impl<ValueType, MostInheritedType, index+1, AdditionalAccessors...>
{
public:
typedef AccessorGroup_Impl<ValueType, MostInheritedType, index+1, AdditionalAccessors...> Base;
using Base::Accessor;
inline AccessorType& Accessor(Specialized<index>)
{
return m_thisAccessor;
}
inline AccessorType const& Accessor(Specialized<index>) const
{
return m_thisAccessor;
}
protected:
template< typename A, typename... B >
friend class sprawl::collections::HashMap;
template< typename A, typename B, size_t C, typename... D >
friend class sprawl::collections::detail::HashMap_Impl;
template<typename A, typename B>
friend class sprawl::MapIterator;
AccessorGroup_Impl(ValueType const& value)
: Base(value)
, m_thisAccessor(this->m_value)
, m_nextThisAccessor(nullptr)
, m_prevThisAccessor(nullptr)
, m_thisIdx(0)
{
//
}
AccessorGroup_Impl(ValueType&& value)
: Base(std::move(value))
, m_thisAccessor(this->m_value)
, m_nextThisAccessor(nullptr)
, m_prevThisAccessor(nullptr)
, m_thisIdx(0)
{
//
}
AccessorGroup_Impl(AccessorGroup_Impl const& other)
: Base(other)
, m_thisAccessor(other.m_thisAccessor)
, m_nextThisAccessor(nullptr)
, m_prevThisAccessor(nullptr)
, m_thisIdx(0)
{
//
}
//Note: In all of these constructors, this->m_value isn't initialized yet.
//But accessors hold a reference to it, and don't do anything with it during initialization.
//So it's safe to give them the memory address even though we haven't initialized it yet.
//Case one: Exactly two parameters, first one is key type, second one is value type.
//Initialize with key, pass value up.
template<typename Param1, typename = typename std::enable_if<std::is_constructible<typename AccessorType::arg_type const&, Param1>::value>::type>
AccessorGroup_Impl(Param1 const& key, ValueType const& value)
: Base(value)
, m_thisAccessor(this->m_value, key)
, m_nextThisAccessor(nullptr)
, m_prevThisAccessor(nullptr)
, m_thisIdx(0)
{
//
}
//Case two: Three or more parameters, first one is key type. Second one can't be value because value is last, so if we have a third parameter, second isn't value.
//Initialize with key, pass remaining parameters up.
template<typename Param1, typename Param2, typename... Params, typename = typename std::enable_if<std::is_constructible<typename AccessorType::arg_type const&, Param1>::value>::type>
AccessorGroup_Impl(Param1 const& key, Param2&& nextParam, Params&&... moreParams)
: Base(std::forward<Param2>(nextParam), std::forward<Params>(moreParams)...)
, m_thisAccessor(this->m_value, key)
, m_nextThisAccessor(nullptr)
, m_prevThisAccessor(nullptr)
, m_thisIdx(0)
{
//
}
//Case three: Exactly two parameters, first one is not key type, second one's type doesn't matter.
//Pass both parameters up.
template<typename Param1, typename Param2, typename = typename std::enable_if<!std::is_constructible<typename AccessorType::arg_type const&, Param1>::value>::type>
AccessorGroup_Impl(Param1&& firstParam, Param2&& nextParam)
: Base(std::forward<Param1>(firstParam), std::forward<Param2>(nextParam))
, m_thisAccessor(this->m_value)
, m_nextThisAccessor(nullptr)
, m_prevThisAccessor(nullptr)
, m_thisIdx(0)
{
//
}
//Case four: More than two parameters, first one is not key type.
//Pass all parameters up.
template<typename Param1, typename Param2, typename... Params, typename = typename std::enable_if<!std::is_constructible<typename AccessorType::arg_type const&, Param1>::value>::type>
AccessorGroup_Impl(Param1&& firstParam, Param2&& secondParam, Params&&... moreKeys)
: Base(std::forward<Param1>(firstParam), std::forward<Param2>(secondParam), std::forward<Params>(moreKeys)...)
, m_thisAccessor(this->m_value)
, m_nextThisAccessor(nullptr)
, m_prevThisAccessor(nullptr)
, m_thisIdx(0)
{
//
}
using Base::Next;
inline MostInheritedType* Next(Specialized<index>)
{
return m_nextThisAccessor;
}
using Base::Prev;
inline MostInheritedType* Prev(Specialized<index>)
{
return m_prevThisAccessor;
}
using Base::SetNext;
inline void SetNext(Specialized<index>, MostInheritedType* next)
{
m_nextThisAccessor = next;
}
using Base::SetPrev;
inline void SetPrev(Specialized<index>, MostInheritedType* prev)
{
m_prevThisAccessor = prev;
}
using Base::Idx;
inline size_t Idx(Specialized<index>)
{
return m_thisIdx;
}
using Base::SetIndex;
inline void SetIndex(Specialized<index>, size_t idx)
{
m_thisIdx = idx;
}
using Base::GetHash;
inline size_t GetHash(Specialized<index>)
{
return m_thisHash;
}
using Base::SetHash;
inline void SetHash(Specialized<index>, size_t hash)
{
m_thisHash = hash;
}
AccessorType m_thisAccessor;
MostInheritedType* m_nextThisAccessor;
MostInheritedType* m_prevThisAccessor;
size_t m_thisIdx;
size_t m_thisHash;
};
template<typename ValueType, typename... Accessors>
class AccessorGroup : public AccessorGroup_Impl<ValueType, AccessorGroup<ValueType, Accessors...>, 0, Accessors...>
{
public:
typedef AccessorGroup_Impl<ValueType, AccessorGroup<ValueType, Accessors...>, 0, Accessors...> Base;
typedef Base* BasePtr;
template<typename Param1, typename Param2, typename... Params>
AccessorGroup(Param1&& firstParam, Param2&& secondParam, Params&&... params)
: Base(std::forward<Param1>(firstParam), std::forward<Param2>(secondParam), std::forward<Params>(params)...)
{
//
}
AccessorGroup(ValueType const& value)
: Base(value)
{
//
}
AccessorGroup(ValueType&& value)
: Base(std::move(value))
{
//
}
AccessorGroup(AccessorGroup const& other)
: Base(other)
{
//
}
template<int i>
auto Key() const -> decltype(BasePtr(nullptr)->Accessor(Specialized<i>()).Key())
{
return this->Accessor(Specialized<i>()).Key();
}
auto Key() const -> decltype(BasePtr(nullptr)->Accessor(Specialized<0>()).Key())
{
return this->Accessor(Specialized<0>()).Key();
}
};
}
}
}
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #6 | 14220 | ShadauxCat |
-Added binary tree implementation (red/black tree) with same multi-key interface as hashmap -Renamed AccessorGroup to MapAccessorGroup to make room for TreeAccessorGroup, which is a lot of duplicated code but had to meet some specific requirements that couldn't be easily fit into the existing AccessorGroup -Fixed HashMap::Clear() not resetting size to 0 -Fixed HashMap::Erase() neither decrementing size nor freeing memory -Changed HashMap to grow before insert instead of after (delaying needed growth until the next insert instead of growing when it detects the next insert will need it) -Fixed a style issue for private function HashMap_Impl::insertHere_() -Fully removed support for Visual Studio 2012 as I have neither the need nor the desire to continue supporting it. The doubled maintenance cost is too high. -Included array unit test that got missed before #review-14221 |
||
| #5 | 14081 | ShadauxCat |
-Switching order of keys and values in HashMap::insert(). Keys now come first - a number of parameters equal to the number of keys. (Simple case is simply insert(key, value)) -Added move constructors to AccessorGroup so things can be inserted into the map via rvalue references -Fixed ForwardList's copy constructor copying things in reverse and added a unit test to make sure it doesn't happen again. #review-14079 |
||
| #4 | 14068 | ShadauxCat |
Fixed broken copy constructor in AccessorGroup with a KeyAccessor #review-14069 |
||
| #3 | 14066 | ShadauxCat |
-Improved iterating in hashmap - range-based for now gives the ability to access both key and value instead of just value -Slightly improved some of the template aliases -Mega-deprecated VC11 support. Probably doesn't compile anymore. Maintaining it is too much of a headache. #review-14067 |
||
| #2 | 14015 | ShadauxCat |
-Made reference counts in strings atomic -Fixed an issue where items that were implicitly convertible to a hash map's value could not be inserted without explicit construction. (i.e., inserting a String object as map.insert("myString") would fail; it had to be map.insert(sprawl::String("myString"))) -Added template aliases for HashMap to simplify construction in simple single key/single value case -Deprecated MSVC11 support. |
||
| #1 | 11496 | ShadauxCat | Initial checkin: Current states for csbuild and libSprawl |