Skip to content

Commit

Permalink
Merge pull request #2319 from nlohmann/issue2315
Browse files Browse the repository at this point in the history
Fix a bug due to missing overloads in ordered_map container
  • Loading branch information
nlohmann committed Jul 31, 2020
2 parents 35daa5c + 2326abc commit 1eedee5
Show file tree
Hide file tree
Showing 6 changed files with 983 additions and 407 deletions.
106 changes: 103 additions & 3 deletions include/nlohmann/ordered_map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
using mapped_type = T;
using Container = std::vector<std::pair<const Key, T>, Allocator>;
using typename Container::iterator;
using typename Container::const_iterator;
using typename Container::size_type;
using typename Container::value_type;

Expand All @@ -30,7 +31,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
ordered_map(std::initializer_list<T> init, const Allocator& alloc = Allocator() )
: Container{init, alloc} {}

std::pair<iterator, bool> emplace(key_type&& key, T&& t)
std::pair<iterator, bool> emplace(const key_type& key, T&& t)
{
for (auto it = this->begin(); it != this->end(); ++it)
{
Expand All @@ -43,9 +44,40 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
return {--this->end(), true};
}

T& operator[](Key&& key)
T& operator[](const Key& key)
{
return emplace(std::move(key), T{}).first->second;
return emplace(key, T{}).first->second;
}

const T& operator[](const Key& key) const
{
return at(key);
}

T& at(const Key& key)
{
for (auto it = this->begin(); it != this->end(); ++it)
{
if (it->first == key)
{
return it->second;
}
}

throw std::out_of_range("key not found");
}

const T& at(const Key& key) const
{
for (auto it = this->begin(); it != this->end(); ++it)
{
if (it->first == key)
{
return it->second;
}
}

throw std::out_of_range("key not found");
}

size_type erase(const Key& key)
Expand All @@ -66,6 +98,74 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
}
return 0;
}

iterator erase(iterator pos)
{
auto it = pos;

// Since we cannot move const Keys, re-construct them in place
for (auto next = it; ++next != this->end(); ++it)
{
it->~value_type(); // Destroy but keep allocation
new (&*it) value_type{std::move(*next)};
}
Container::pop_back();
return pos;
}

size_type count(const Key& key) const
{
for (auto it = this->begin(); it != this->end(); ++it)
{
if (it->first == key)
{
return 1;
}
}
return 0;
}

iterator find(const Key& key)
{
for (auto it = this->begin(); it != this->end(); ++it)
{
if (it->first == key)
{
return it;
}
}
return Container::end();
}

const_iterator find(const Key& key) const
{
for (auto it = this->begin(); it != this->end(); ++it)
{
if (it->first == key)
{
return it;
}
}
return Container::end();
}

std::pair<iterator, bool> insert( value_type&& value )
{
return emplace(value.first, std::move(value.second));
}

std::pair<iterator, bool> insert( const value_type& value )
{
for (auto it = this->begin(); it != this->end(); ++it)
{
if (it->first == value.first)
{
return {it, false};
}
}
Container::push_back(value);
return {--this->end(), true};
}
};

} // namespace nlohmann
106 changes: 103 additions & 3 deletions single_include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16408,6 +16408,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
using mapped_type = T;
using Container = std::vector<std::pair<const Key, T>, Allocator>;
using typename Container::iterator;
using typename Container::const_iterator;
using typename Container::size_type;
using typename Container::value_type;

Expand All @@ -16420,7 +16421,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
ordered_map(std::initializer_list<T> init, const Allocator& alloc = Allocator() )
: Container{init, alloc} {}

std::pair<iterator, bool> emplace(key_type&& key, T&& t)
std::pair<iterator, bool> emplace(const key_type& key, T&& t)
{
for (auto it = this->begin(); it != this->end(); ++it)
{
Expand All @@ -16433,9 +16434,40 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
return {--this->end(), true};
}

T& operator[](Key&& key)
T& operator[](const Key& key)
{
return emplace(std::move(key), T{}).first->second;
return emplace(key, T{}).first->second;
}

const T& operator[](const Key& key) const
{
return at(key);
}

T& at(const Key& key)
{
for (auto it = this->begin(); it != this->end(); ++it)
{
if (it->first == key)
{
return it->second;
}
}

throw std::out_of_range("key not found");
}

const T& at(const Key& key) const
{
for (auto it = this->begin(); it != this->end(); ++it)
{
if (it->first == key)
{
return it->second;
}
}

throw std::out_of_range("key not found");
}

size_type erase(const Key& key)
Expand All @@ -16456,6 +16488,74 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
}
return 0;
}

iterator erase(iterator pos)
{
auto it = pos;

// Since we cannot move const Keys, re-construct them in place
for (auto next = it; ++next != this->end(); ++it)
{
it->~value_type(); // Destroy but keep allocation
new (&*it) value_type{std::move(*next)};
}
Container::pop_back();
return pos;
}

size_type count(const Key& key) const
{
for (auto it = this->begin(); it != this->end(); ++it)
{
if (it->first == key)
{
return 1;
}
}
return 0;
}

iterator find(const Key& key)
{
for (auto it = this->begin(); it != this->end(); ++it)
{
if (it->first == key)
{
return it;
}
}
return Container::end();
}

const_iterator find(const Key& key) const
{
for (auto it = this->begin(); it != this->end(); ++it)
{
if (it->first == key)
{
return it;
}
}
return Container::end();
}

std::pair<iterator, bool> insert( value_type&& value )
{
return emplace(value.first, std::move(value.second));
}

std::pair<iterator, bool> insert( const value_type& value )
{
for (auto it = this->begin(); it != this->end(); ++it)
{
if (it->first == value.first)
{
return {it, false};
}
}
Container::push_back(value);
return {--this->end(), true};
}
};

} // namespace nlohmann
Expand Down
4 changes: 3 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,12 @@ set(files
src/unit-msgpack.cpp
src/unit-noexcept.cpp
src/unit-ordered_json.cpp
src/unit-ordered_map.cpp
src/unit-pointer_access.cpp
src/unit-readme.cpp
src/unit-reference_access.cpp
src/unit-regression.cpp
src/unit-regression1.cpp
src/unit-regression2.cpp
src/unit-serialization.cpp
src/unit-testsuites.cpp
src/unit-to_chars.cpp
Expand Down

0 comments on commit 1eedee5

Please sign in to comment.