LSST Applications g070148d5b3+33e5256705,g0d53e28543+25c8b88941,g0da5cf3356+2dd1178308,g1081da9e2a+62d12e78cb,g17e5ecfddb+7e422d6136,g1c76d35bf8+ede3a706f7,g295839609d+225697d880,g2e2c1a68ba+cc1f6f037e,g2ffcdf413f+853cd4dcde,g38293774b4+62d12e78cb,g3b44f30a73+d953f1ac34,g48ccf36440+885b902d19,g4b2f1765b6+7dedbde6d2,g5320a0a9f6+0c5d6105b6,g56b687f8c9+ede3a706f7,g5c4744a4d9+ef6ac23297,g5ffd174ac0+0c5d6105b6,g6075d09f38+66af417445,g667d525e37+2ced63db88,g670421136f+2ced63db88,g71f27ac40c+2ced63db88,g774830318a+463cbe8d1f,g7876bc68e5+1d137996f1,g7985c39107+62d12e78cb,g7fdac2220c+0fd8241c05,g96f01af41f+368e6903a7,g9ca82378b8+2ced63db88,g9d27549199+ef6ac23297,gabe93b2c52+e3573e3735,gb065e2a02a+3dfbe639da,gbc3249ced9+0c5d6105b6,gbec6a3398f+0c5d6105b6,gc9534b9d65+35b9f25267,gd01420fc67+0c5d6105b6,geee7ff78d7+a14128c129,gf63283c776+ede3a706f7,gfed783d017+0c5d6105b6,w.2022.47
LSST Data Management Base Package
Loading...
Searching...
No Matches
SimpleGenericMap.h
Go to the documentation of this file.
1// -*- LSST-C++ -*-
2/*
3 * This file is part of afw.
4 *
5 * Developed for the LSST Data Management System.
6 * This product includes software developed by the LSST Project
7 * (https://www.lsst.org).
8 * See the COPYRIGHT file at the top-level directory of this distribution
9 * for details of code ownership.
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 */
24
25#ifndef LSST_AFW_TYPEHANDLING_SIMPLEGENERICMAP_H
26#define LSST_AFW_TYPEHANDLING_SIMPLEGENERICMAP_H
27
28#include <exception>
29#include <sstream>
30#include <unordered_map>
31#include <utility>
32#include <variant>
33
35
36namespace lsst {
37namespace afw {
38namespace typehandling {
39
48template <typename K>
49class SimpleGenericMap final : public MutableGenericMap<K> {
50protected:
51 using typename GenericMap<K>::StorableType;
53
54public:
55 SimpleGenericMap() = default;
56 SimpleGenericMap(SimpleGenericMap const& other) = default;
57 SimpleGenericMap(SimpleGenericMap&&) noexcept = default;
65 SimpleGenericMap(GenericMap<K> const& other) : _storage(_convertStorage(other)), _keyView(other.keys()) {}
66 virtual ~SimpleGenericMap() noexcept = default;
67
68 SimpleGenericMap& operator=(SimpleGenericMap const& other) {
69 std::vector<K> newKeys = other._keyView;
70 _storage = other._storage;
71 // strong exception safety because no exceptions can occur past this point
72 using std::swap;
73 swap(_keyView, newKeys);
74 return *this;
75 }
77 SimpleGenericMap& operator=(GenericMap<K> const& other) {
78 std::vector<K> newKeys = other.keys();
79 // strong exception safety: unordered_map is nothrow move-assignable and
80 // vector is nothrow swappable, so no exceptions can occur after _convertStorage returns
81 _storage = _convertStorage(other);
82 using std::swap;
83 swap(_keyView, newKeys);
84 return *this;
85 }
86
87 typename GenericMap<K>::size_type size() const noexcept override { return _storage.size(); }
88
89 bool empty() const noexcept override { return _storage.empty(); }
90
91 typename GenericMap<K>::size_type max_size() const noexcept override {
92 return std::min(_storage.max_size(), _keyView.max_size());
93 }
94
95 bool contains(K const& key) const override { return _storage.count(key) > 0; }
96
97 std::vector<K> const& keys() const noexcept override { return _keyView; }
98
99 void clear() noexcept override {
100 _storage.clear();
101 _keyView.clear();
102 }
103
104protected:
105 ConstValueReference unsafeLookup(K key) const override {
106 try {
107 return std::visit(
108 [](auto const & v) { return ConstValueReference(std::cref(v)); },
109 _storage.at(key)
110 );
111 } catch (std::out_of_range& e) {
112 std::stringstream message;
113 message << "Key not found: " << key;
115 }
116 }
117
118 bool unsafeInsert(K key, StorableType&& value) override {
119 std::vector<K> newKeys = _keyView;
120 newKeys.emplace_back(key);
121 bool inserted = _storage.emplace(key, std::move(value)).second;
122 // strong exception safety because no exceptions can occur past this point
123 if (inserted) {
124 // _storage did not previously include key, so the key appended to newKeys is unique
125 using std::swap;
126 swap(_keyView, newKeys);
127 }
128 return inserted;
129 }
130
131 bool unsafeErase(K key) override {
132 std::vector<K> newKeys = _keyView;
133 for (auto it = newKeys.cbegin(); it != newKeys.cend();) {
134 if (*it == key) {
135 it = newKeys.erase(it);
136 } else {
137 ++it;
138 }
139 }
140 // strong exception safety because no exceptions can occur past this point
141 bool erased = _storage.erase(key) > 0;
142 if (erased) {
143 using std::swap;
144 swap(_keyView, newKeys);
145 }
146 return erased;
147 }
148
149private:
150 // StorableType is a value, so we might as well use it in the implementation
152 std::vector<K> _keyView;
153 // Class invariant: the elements of _keyView are unique
154 // Class invariant: the elements of _keyView and the keys of _storage are the same
155 // Class invariant: the elements of _keyView are arranged in insertion order, oldest to newest
156
165 static std::unordered_map<K, StorableType> _convertStorage(GenericMap<K> const& map) {
167 map.apply([&newStorage](K const& key, auto const& value) { newStorage.emplace(key, value); });
168 return newStorage;
169 }
170};
171
172} // namespace typehandling
173} // namespace afw
174} // namespace lsst
175
176#endif
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
T at(T... args)
T cbegin(T... args)
Interface for a heterogeneous map.
Definition: GenericMap.h:79
decltype(_typeToConstRef(std::declval< StorableType >())) ConstValueReference
A type-agnostic reference to the value stored inside the map.
Definition: GenericMap.h:369
std::variant< bool, int, long, long long, float, double, std::string, PolymorphicValue, std::shared_ptr< Storable const > > StorableType
The types that can be stored in a map.
Definition: GenericMap.h:360
auto apply(Visitor &&visitor) const
Apply an operation to each key-value pair in the map.
Definition: GenericMap.h:309
Interface for a GenericMap that allows element addition and removal.
Definition: GenericMap.h:597
A GenericMap that allows insertion and deletion of arbitrary values.
virtual ~SimpleGenericMap() noexcept=default
void clear() noexcept override
Remove all of the mappings from this map.
std::vector< K > const & keys() const noexcept override
Return the set of all keys, without type information.
GenericMap< K >::size_type size() const noexcept override
Return the number of key-value pairs in the map.
SimpleGenericMap(SimpleGenericMap const &other)=default
bool unsafeErase(K key) override
Remove the mapping for a key from this map, if it exists.
bool empty() const noexcept override
Return true if this map contains no key-value pairs.
SimpleGenericMap & operator=(SimpleGenericMap &&) noexcept=default
bool contains(K const &key) const override
Return true if this map contains a mapping whose key has the specified label.
ConstValueReference unsafeLookup(K key) const override
Return a reference to the mapped value of the element with key equal to key.
GenericMap< K >::size_type max_size() const noexcept override
Return the maximum number of elements the container is able to hold due to system or library implemen...
bool unsafeInsert(K key, StorableType &&value) override
Create a new mapping with key equal to key and value equal to value.
SimpleGenericMap(SimpleGenericMap &&) noexcept=default
Reports attempts to access elements outside a valid range of indices.
Definition: Runtime.h:89
T clear(T... args)
T count(T... args)
T emplace_back(T... args)
T emplace(T... args)
T empty(T... args)
T cend(T... args)
T erase(T... args)
T max_size(T... args)
T min(T... args)
T move(T... args)
T cref(T... args)
T size(T... args)
T str(T... args)
T swap(T... args)
T throw_with_nested(T... args)