25#ifndef LSST_AFW_TYPEHANDLING_GENERICMAP_H
26#define LSST_AFW_TYPEHANDLING_GENERICMAP_H
47namespace typehandling {
108 template <typename T, typename
std::enable_if_t<!detail::IS_SMART_PTR<T>,
int> = 0>
111 return const_cast<T&
>(
static_cast<const GenericMap&
>(*this).
at(key));
114 template <
typename T,
typename std::enable_if_t<!detail::IS_SMART_PTR<T>,
int> = 0>
120 template <typename T, typename std::enable_if_t<std::is_base_of<Storable, T>::value,
int> = 0>
132 virtual
bool empty() const noexcept = 0;
156 template <typename T>
193 template <
typename T>
196 return _contains(key);
229 virtual
bool operator==(
GenericMap const& other) const noexcept {
230 auto keys1 = this->
keys();
231 auto keys2 = other.keys();
235 for (K
const& key : keys1) {
308 template <
class Visitor>
309 auto apply(Visitor&& visitor)
const {
311 return _apply(visitor);
330 template <
class Visitor>
333 return _apply(visitor);
343 template <
typename... Types>
344 static std::variant<std::reference_wrapper<Types>...> _typeToRef(
345 std::variant<Types...>
const&)
noexcept;
346 template <
typename... Types>
347 static std::variant<std::reference_wrapper<std::add_const_t<Types>>...> _typeToConstRef(
348 std::variant<Types...>
const&)
noexcept;
403 template <
typename T,
404 typename std::enable_if_t<
406 T
const& _at(
Key<K, T> const& key)
const {
408 "Due to implementation constraints, const keys are not supported.");
411 return std::get<std::reference_wrapper<T const>>(foo);
414 message <<
"Key " << key <<
" not found, but a key labeled " << key.
getId() <<
" is present.";
420 template <typename T, typename std::enable_if_t<std::is_base_of<Storable, T>::value,
int> = 0>
421 T
const& _at(Key<K, T>
const& key)
const {
423 "Due to implementation constraints, const keys are not supported.");
426 Storable
const& value = std::get<std::reference_wrapper<PolymorphicValue const>>(foo).get();
427 T
const* typedPointer =
dynamic_cast<T const*
>(&value);
428 if (typedPointer !=
nullptr) {
429 return *typedPointer;
432 message <<
"Key " << key <<
" not found, but a key labeled " << key.getId() <<
" is present.";
433 throw LSST_EXCEPT(pex::exceptions::OutOfRangeError, message.
str());
437 message <<
"Key " << key <<
" not found, but a key labeled " << key.getId() <<
" is present.";
438 throw LSST_EXCEPT(pex::exceptions::OutOfRangeError, message.
str());
443 template <typename T, typename std::enable_if_t<std::is_base_of<Storable, T>::value,
int> = 0>
446 "Due to implementation constraints, pointers to non-const are not supported.");
449 auto pointer = std::get<std::reference_wrapper<std::shared_ptr<Storable const>
const>>(foo).get();
450 if (pointer ==
nullptr) {
457 if (typedPointer.use_count() > 0) {
461 message <<
"Key " << key <<
" not found, but a key labeled " << key.getId() <<
" is present.";
462 throw LSST_EXCEPT(pex::exceptions::OutOfRangeError, message.
str());
466 message <<
"Key " << key <<
" not found, but a key labeled " << key.getId() <<
" is present.";
467 throw LSST_EXCEPT(pex::exceptions::OutOfRangeError, message.
str());
472 template <
typename T,
473 typename std::enable_if_t<
475 bool _contains(Key<K, T>
const& key)
const {
482 return std::holds_alternative<std::reference_wrapper<T const>>(foo);
486 template <typename T, typename std::enable_if_t<std::is_base_of<Storable, T>::value,
int> = 0>
487 bool _contains(Key<K, T>
const& key)
const {
494 auto refwrap = std::get_if<std::reference_wrapper<PolymorphicValue const>>(&foo);
496 Storable
const &
value = refwrap->get();
497 auto asT =
dynamic_cast<T const*
>(&
value);
498 return asT !=
nullptr;
505 template <typename T, typename std::enable_if_t<std::is_base_of<Storable, T>::value,
int> = 0>
508 "Due to implementation constraints, pointers to non-const are not supported.");
516 auto pointer = std::get<std::reference_wrapper<std::shared_ptr<Storable const>
const>>(foo).get();
517 if (pointer ==
nullptr) {
523 return typedPointer.use_count() > 0;
532 template <
class Visitor>
533 using _VisitorResult = std::invoke_result_t<Visitor, K&&, bool&>;
537 template <
class Visitor,
typename std::enable_if_t<std::is_
void<_VisitorResult<Visitor>>::value,
int> = 0>
538 void _apply(Visitor&& visitor)
const {
540 for (K
const& key :
keys()) {
541 std::variant<K> varKey = key;
547 template <
class Visitor,
548 typename std::enable_if_t<!std::is_void<_VisitorResult<Visitor>>::value,
int> = 0>
549 auto _apply(Visitor&& visitor)
const {
553 for (K
const& key :
keys()) {
554 std::variant<K> varKey = key;
555 results.emplace_back(std::visit(wrapped, varKey,
unsafeLookup(key)));
561 template <
class Visitor,
typename std::enable_if_t<std::is_
void<_VisitorResult<Visitor>>::value,
int> = 0>
562 void _apply(Visitor&& visitor) {
564 for (K
const& key :
keys()) {
565 std::variant<K> varKey = key;
571 template <
class Visitor,
572 typename std::enable_if_t<!std::is_void<_VisitorResult<Visitor>>::value,
int> = 0>
573 auto _apply(Visitor&& visitor) {
578 for (K
const& key :
keys()) {
579 std::variant<K> varKey = key;
580 results.emplace_back(std::visit(wrapped, varKey,
unsafeLookup(key)));
629 template <typename T>
630 bool insert(
Key<K, T> const& key, T const& value) {
653 template <
typename T>
655 auto strongKey = makeKey<T>(key);
657 auto result = make_pair(strongKey,
false);
675 template <
typename T>
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Interface for a heterogeneous map.
T & at(Key< K, T > const &key)
Return a reference to the mapped value of the element with key equal to key.
size_type count(Key< K, T > const &key) const
Return the number of elements mapped to the specified key.
T const & at(Key< K, T > const &key) const
Return a reference to the mapped value of the element with key equal to key.
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.
std::shared_ptr< T > at(Key< K, std::shared_ptr< T > > const &key) const
Return a reference to the mapped value of the element with key equal to key.
virtual ConstValueReference unsafeLookup(K key) const =0
Return a reference to the mapped value of the element with key equal to key.
bool contains(Key< K, T > const &key) const
Return true if this map contains a mapping for the specified key.
decltype(_typeToRef(std::declval< StorableType >())) ValueReference
A type-agnostic reference to the value stored inside the map.
virtual bool empty() const noexcept=0
Return true if this map contains no key-value pairs.
auto apply(Visitor &&visitor)
Apply a modifying operation to each key-value pair in the map.
virtual std::vector< K > const & keys() const noexcept=0
Return the set of all keys, without type information.
decltype(_typeToConstRef(std::declval< StorableType >())) ConstValueReference
A type-agnostic reference to the value stored inside the map.
virtual size_type max_size() const noexcept=0
Return the maximum number of elements the container is able to hold due to system or library implemen...
virtual size_type size() const noexcept=0
Return the number of key-value pairs in the map.
auto apply(Visitor &&visitor) const
Apply an operation to each key-value pair in the map.
ValueReference unsafeLookup(K key)
Return a reference to the mapped value of the element with key equal to key.
virtual ~GenericMap() noexcept=default
virtual bool contains(K const &key) const =0
Return true if this map contains a mapping whose key has the specified label.
bool operator!=(GenericMap const &other) const
Test for map equality.
Key for type-safe lookup in a GenericMap.
constexpr K const & getId() const noexcept
Return the identifier of this field.
Interface for a GenericMap that allows element addition and removal.
virtual bool unsafeInsert(K key, StorableType &&value)=0
Create a new mapping with key equal to key and value equal to value.
virtual bool unsafeErase(K key)=0
Remove the mapping for a key from this map, if it exists.
virtual ~MutableGenericMap() noexcept=default
bool insert(Key< K, T > const &key, T const &value)
Insert an element into the map, if the map doesn't already contain a mapping with the same or a confl...
std::pair< Key< K, T >, bool > insert(K const &key, T const &value)
Insert an element into the map, if the map doesn't already contain a mapping with a conflicting key.
bool erase(Key< K, T > const &key)
Remove the mapping for a key from this map, if it exists.
virtual void clear() noexcept=0
Remove all of the mappings from this map.
Container that passes Storable objects by value while preserving type.
Reports attempts to access elements outside a valid range of indices.
T is_permutation(T... args)
std::reference_wrapper< T > refwrap_const_cast(std::reference_wrapper< T const > const &r)
refwrap_visitor< F > make_refwrap_visitor(F &&func)
decltype(sizeof(void *)) size_t