blob: f3caeb0cf66943cfb9c697e6cb3b7fbb32cacaaa (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
/******************************************************************************
*
* Copyright (C) 1997-2020 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
* Documents produced by Doxygen are derivative works derived from the
* input used in their production; they are not affected by this license.
*
*/
#ifndef LINKEDMAP_H
#define LINKEDMAP_H
#include <unordered_map>
#include <vector>
#include <memory>
#include <string>
//! @brief Container class representing a vector of objects with unique keys.
//! @details Elements can be quickly looked up given the key.
//! When adding objects the order of addition is kept, and used while iterating.
template<class T>
class LinkedMap
{
public:
using Ptr = std::unique_ptr<T>;
using Vec = std::vector<Ptr>;
using Map = std::unordered_map<std::string,T*>;
using iterator = typename Vec::iterator;
using const_iterator = typename Vec::const_iterator;
//! find an element given the key.
//! Returns a pointer to the element if found or nullptr if it is not found.
const T *find(const char *key) const
{
auto it = m_lookup.find(key);
return it!=m_lookup.end() ? it->second : nullptr;
}
//! non-const wrapper for find() const
T* find(const char *key)
{
return const_cast<T*>(static_cast<const LinkedMap&>(*this).find(key));
}
//! Adds a new element to the ordered set if it was not added already.
//! Return a non-owning pointer to the newly added item, or to the existing item if it was
//! already inserted before.
template<class...Args>
T *add(const char *key, Args&&... args)
{
T *result = find(key);
if (result==nullptr)
{
Ptr ptr = std::make_unique<T>(key,std::forward<Args>(args)...);
result = ptr.get();
m_lookup.insert({key ? std::string(key) : std::string(),result});
m_entries.push_back(std::move(ptr));
}
return result;
}
iterator begin() { return m_entries.begin(); }
iterator end() { return m_entries.end(); }
const_iterator begin() const { return m_entries.cbegin(); }
const_iterator end() const { return m_entries.cend(); }
bool empty() const { return m_entries.empty(); }
int size() const { return m_entries.size(); }
void clear()
{
m_entries.clear();
m_lookup.clear();
}
private:
Map m_lookup;
Vec m_entries;
};
#endif
|