LSST Applications g0b6bd0c080+a72a5dd7e6,g1182afd7b4+2a019aa3bb,g17e5ecfddb+2b8207f7de,g1d67935e3f+06cf436103,g38293774b4+ac198e9f13,g396055baef+6a2097e274,g3b44f30a73+6611e0205b,g480783c3b1+98f8679e14,g48ccf36440+89c08d0516,g4b93dc025c+98f8679e14,g5c4744a4d9+a302e8c7f0,g613e996a0d+e1c447f2e0,g6c8d09e9e7+25247a063c,g7271f0639c+98f8679e14,g7a9cd813b8+124095ede6,g9d27549199+a302e8c7f0,ga1cf026fa3+ac198e9f13,ga32aa97882+7403ac30ac,ga786bb30fb+7a139211af,gaa63f70f4e+9994eb9896,gabf319e997+ade567573c,gba47b54d5d+94dc90c3ea,gbec6a3398f+06cf436103,gc6308e37c7+07dd123edb,gc655b1545f+ade567573c,gcc9029db3c+ab229f5caf,gd01420fc67+06cf436103,gd877ba84e5+06cf436103,gdb4cecd868+6f279b5b48,ge2d134c3d5+cc4dbb2e3f,ge448b5faa6+86d1ceac1d,gecc7e12556+98f8679e14,gf3ee170dca+25247a063c,gf4ac96e456+ade567573c,gf9f5ea5b4d+ac198e9f13,gff490e6085+8c2580be5c,w.2022.27
LSST Data Management Base Package
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 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 emplace_back(T... args)
T emplace(T... args)
T cend(T... args)
T erase(T... args)
T min(T... args)
T move(T... args)
void swap(PolymorphicValue &lhs, PolymorphicValue &rhs) noexcept
Swap specialization for PolymorphicValue.
A base class for image defects.
T cref(T... args)
T str(T... args)
T swap(T... args)
T throw_with_nested(T... args)