Radium Engine  1.5.20
Loading...
Searching...
No Matches
BijectiveAssociation.hpp
1#pragma once
2
3#include <Core/Utils/StdOptional.hpp>
4
5#include <algorithm>
6#include <initializer_list>
7#include <iostream>
8#include <map>
9
10namespace Ra {
11namespace Core {
12namespace Utils {
13
19template <typename T1, typename T2>
21{
22 public:
23 using key_type = T1;
24 using value_type = T2;
27
32
36 explicit BijectiveAssociation() = default;
37
43
49
64
70
80
86
92
97 value_type value( const key_type& key ) const;
98
104 optional<value_type> valueIfExists( const key_type& key ) const;
105
110 key_type key( const value_type& value ) const;
111
117 optional<key_type> keyIfExists( const value_type& value ) const;
118
122 typename std::map<key_type, value_type>::const_iterator begin() const noexcept;
123
125 typename std::map<key_type, value_type>::const_iterator cbegin() const noexcept;
126
130 typename std::map<key_type, value_type>::const_iterator end() const noexcept;
131
133 typename std::map<key_type, value_type>::const_iterator cend() const noexcept;
134
138 size_t size() const;
139
140 private:
141 key_to_value_map m_keyToValue;
142 value_to_key_map m_valueToKey;
143};
144
145template <typename T1, typename T2>
147 std::initializer_list<std::pair<key_type, value_type>> pairs ) {
148 for ( auto& p : pairs ) {
149 m_valueToKey.insert( { p.second, p.first } );
150 m_keyToValue.insert( p );
151 }
152}
153
154template <typename T1, typename T2>
156 auto [i1, r1] = m_valueToKey.insert( { p.second, p.first } );
157 if ( r1 ) {
158 auto [i2, r2] = m_keyToValue.insert( std::move( p ) );
159 return r2;
160 }
161 return false;
162}
163
164template <typename T1, typename T2>
165bool BijectiveAssociation<T1, T2>::insert( key_type key, value_type value ) {
166 return insert( { key, value } );
167}
168
169template <typename T1, typename T2>
170void BijectiveAssociation<T1, T2>::replace( key_type key, value_type value ) {
171 // clean previously set association
172 auto it1 = std::find_if(
173 m_keyToValue.begin(),
174 m_keyToValue.end(),
175 [&value]( const typename key_to_value_map::value_type& v ) { return value == v.second; } );
176
177 if ( it1 != m_keyToValue.end() ) m_keyToValue.erase( it1 );
178
179 auto it2 = std::find_if(
180 m_valueToKey.begin(),
181 m_valueToKey.end(),
182 [&key]( const typename value_to_key_map::value_type& v ) { return key == v.second; } );
183
184 if ( it2 != m_valueToKey.end() ) m_valueToKey.erase( it2 );
185
186 // set new association
187 m_keyToValue[key] = value;
188 m_valueToKey[value] = key;
189}
190template <typename T1, typename T2>
194
195template <typename T1, typename T2>
196bool BijectiveAssociation<T1, T2>::remove( key_type key, value_type value ) {
197 // clean previously set association
198 auto it1 = m_keyToValue.find( key );
199 auto it2 = m_valueToKey.find( value );
200 if ( it1 == m_keyToValue.end() || it2 == m_valueToKey.end() ) return false;
201
202 if ( it1->second != value || it2->second != key ) return false;
203
204 m_keyToValue.erase( it1 );
205 m_valueToKey.erase( it2 );
206 return true;
207}
208
209template <typename T1, typename T2>
211 return remove( p.frist, p.second );
212}
213
214template <typename T1, typename T2>
215typename BijectiveAssociation<T1, T2>::value_type
217 return m_keyToValue.at( k );
218}
219
220template <typename T1, typename T2>
221typename BijectiveAssociation<T1, T2>::key_type
222BijectiveAssociation<T1, T2>::key( const value_type& k ) const {
223 return m_valueToKey.at( k );
224}
225
226template <typename T1, typename T2>
227std::optional<typename BijectiveAssociation<T1, T2>::key_type>
228BijectiveAssociation<T1, T2>::keyIfExists( const value_type& k ) const {
229 auto itr = m_valueToKey.find( k );
230 if ( itr == m_valueToKey.end() ) return {};
231 return itr->second;
232}
233
234template <typename T1, typename T2>
235typename BijectiveAssociation<T1, T2>::value_type
236BijectiveAssociation<T1, T2>::value( const key_type& k ) const {
237 return m_keyToValue.at( k );
238}
239
240template <typename T1, typename T2>
241std::optional<typename BijectiveAssociation<T1, T2>::value_type>
243 auto itr = m_keyToValue.find( k );
244 if ( itr == m_keyToValue.end() ) return {};
245 return itr->second;
246}
247
248template <typename T1, typename T2>
249typename std::map<T1, T2>::const_iterator BijectiveAssociation<T1, T2>::cbegin() const noexcept {
250 return m_keyToValue.cbegin();
251}
252
253template <typename T1, typename T2>
254typename std::map<T1, T2>::const_iterator BijectiveAssociation<T1, T2>::cend() const noexcept {
255 return m_keyToValue.cend();
256}
257
258template <typename T1, typename T2>
259typename std::map<T1, T2>::const_iterator BijectiveAssociation<T1, T2>::begin() const noexcept {
260 return m_keyToValue.begin();
261}
262
263template <typename T1, typename T2>
264typename std::map<T1, T2>::const_iterator BijectiveAssociation<T1, T2>::end() const noexcept {
265 return m_keyToValue.end();
266}
267
268template <typename T1, typename T2>
270 return m_keyToValue.size();
271}
272
273} // namespace Utils
274} // namespace Core
275} // namespace Ra
T at(T... args)
T begin(T... args)
Bijective association between two sets {keys} and {values} having the same cardinality....
value_type value(const key_type &key) const
Gets the value associated to key.
std::map< key_type, value_type >::const_iterator cend() const noexcept
Gets a const iterator at the end of the key to value map.
optional< value_type > valueIfExists(const key_type &key) const
Gets the value associated to key if it exists.
std::map< key_type, value_type >::const_iterator cbegin() const noexcept
Gets a const iterator at beginning of the key to value map.
value_type operator()(const key_type &key) const
Gets the value associated to the key.
bool remove(key_type key, value_type value)
Convenient alias for remove({key, value}).
BijectiveAssociation(std::initializer_list< std::pair< key_type, value_type > > pairs)
Constructor from { <T1, T2> } pairs.
bool remove(std::pair< key_type, value_type > p)
Remove a pair from the association.
std::map< key_type, value_type >::const_iterator begin() const noexcept
Gets a const iterator at beginning of the key to value map.
std::map< key_type, value_type >::const_iterator end() const noexcept
Gets a const iterator at the end of the key to value map.
void replace(std::pair< key_type, value_type > p)
bool insert(std::pair< key_type, value_type > p)
Insert a pair into the association.
bool insert(key_type key, value_type value)
Convenient alias for insert({key, value}).
size_t size() const
Gets the size of the association, i.e. the numer of <Key, Value> pairs.
BijectiveAssociation()=default
Creates an empty association.
void replace(key_type key, value_type value)
Convenient alias of replace({key, value}).
key_type key(const value_type &value) const
Gets the key associated to a value.
optional< key_type > keyIfExists(const value_type &value) const
Gets the key associated to value if it exists.
T end(T... args)
T erase(T... args)
T find_if(T... args)
T insert(T... args)
T move(T... args)
hepler function to manage enum as underlying types in VariableSet
Definition Cage.cpp:3
STL namespace.
T size(T... args)