25 #ifndef LSST_AFW_TYPEHANDLING_GENERICMAP_H 26 #define LSST_AFW_TYPEHANDLING_GENERICMAP_H 35 #include <type_traits> 36 #include <unordered_set> 39 #include "boost/core/demangle.hpp" 40 #include "boost/variant.hpp" 48 namespace typehandling {
62 template <
typename K,
typename V>
79 constexpr
Key(K
id) : id(id) {}
94 constexpr K
const&
getId() const noexcept {
return id; }
106 template <
typename U>
107 constexpr std::enable_if_t<!std::is_same<U, V>::value,
bool>
operator==(
Key<K, U> const&)
const noexcept {
111 template <
typename U>
113 return !(*
this ==
other);
131 template <
typename U>
132 constexpr
bool operator<(Key<K, U>
const&
other)
const noexcept {
134 return comparator(this->
getId(),
other.getId());
161 template <
typename V,
typename K>
184 template <
typename K,
typename V>
186 static const std::string typeStr = boost::core::demangle(
typeid(V).
name());
189 os <<
key.getId() <<
"<" << typeStr << constStr << volatileStr <<
">";
195 template <
typename,
typename =
void>
197 template <
typename T>
198 constexpr
bool IS_SMART_PTR<T, std::enable_if_t<std::is_object<typename T::element_type>::value>> =
true;
229 template <
typename K>
255 template <typename T, typename
std::enable_if_t<!IS_SMART_PTR<T>,
int> = 0>
258 return const_cast<T&
>(
static_cast<const GenericMap&
>(*this).
at(key));
261 template <
typename T,
typename std::enable_if_t<!IS_SMART_PTR<T>,
int> = 0>
267 template <typename T, typename std::enable_if_t<std::is_base_of<Storable, T>::value,
int> = 0>
275 virtual size_type size()
const noexcept = 0;
279 virtual bool empty()
const noexcept = 0;
288 virtual size_type max_size()
const noexcept = 0;
303 template <
typename T>
340 template <
typename T>
343 return _contains(key);
377 auto keys1 = this->
keys();
378 auto keys2 =
other.keys();
382 for (K
const& key : keys1) {
383 if (this->unsafeLookup(key) !=
other.unsafeLookup(key)) {
452 template <
class Visitor>
453 auto apply(Visitor&& visitor)
const {
455 return _apply(visitor);
474 template <
class Visitor>
477 return _apply(visitor);
488 template <
typename... Types>
489 static boost::variant<std::add_lvalue_reference_t<Types>...> _typeToRef(
490 boost::variant<Types...>
const&) noexcept;
491 template <
typename... Types>
492 static boost::variant<std::add_lvalue_reference_t<std::add_const_t<Types>>...> _typeToConstRef(
493 boost::variant<Types...>
const&) noexcept;
537 using NonConstRef = std::add_lvalue_reference_t<
538 std::remove_const_t<std::remove_reference_t<decltype(value)>>>;
540 return const_cast<NonConstRef
>(value);
542 return boost::apply_visitor(removeConst, constRef);
549 template <
typename T,
550 typename std::enable_if_t<
552 T
const& _at(
Key<K, T> const& key)
const {
554 "Due to implementation constraints, const keys are not supported.");
556 auto foo = unsafeLookup(key.
getId());
557 return boost::get<T const&>(foo);
558 }
catch (boost::bad_get
const&) {
560 message <<
"Key " << key <<
" not found, but a key labeled " << key.
getId() <<
" is present.";
566 template <typename T, typename std::enable_if_t<std::is_base_of<Storable, T>::value,
int> = 0>
567 T
const& _at(
Key<K, T> const& key)
const {
569 "Due to implementation constraints, const keys are not supported.");
571 auto foo = unsafeLookup(key.
getId());
573 Storable const& value = boost::get<PolymorphicValue const&>(foo);
574 T
const* typedPointer =
dynamic_cast<T const*
>(&value);
575 if (typedPointer !=
nullptr) {
576 return *typedPointer;
579 message <<
"Key " << key <<
" not found, but a key labeled " << key.
getId() <<
" is present.";
582 }
catch (boost::bad_get
const&) {
584 message <<
"Key " << key <<
" not found, but a key labeled " << key.
getId() <<
" is present.";
590 template <typename T, typename std::enable_if_t<std::is_base_of<Storable, T>::value,
int> = 0>
593 "Due to implementation constraints, const keys are not supported.");
595 auto foo = unsafeLookup(key.
getId());
596 auto pointer = boost::get<std::shared_ptr<Storable>
const&>(foo);
600 if (typedPointer.use_count() > 0) {
604 message <<
"Key " << key <<
" not found, but a key labeled " << key.
getId() <<
" is present.";
607 }
catch (boost::bad_get
const&) {
609 message <<
"Key " << key <<
" not found, but a key labeled " << key.
getId() <<
" is present.";
615 template <
typename T,
616 typename std::enable_if_t<
618 bool _contains(
Key<K, T> const& key)
const {
624 auto foo = unsafeLookup(key.
getId());
627 boost::get<T const&>(foo);
629 }
catch (boost::bad_get
const&) {
635 template <typename T, typename std::enable_if_t<std::is_base_of<Storable, T>::value,
int> = 0>
636 bool _contains(
Key<K, T> const& key)
const {
642 auto foo = unsafeLookup(key.
getId());
645 Storable const& value = boost::get<PolymorphicValue const&>(foo);
646 auto asT =
dynamic_cast<T const*
>(&value);
647 return asT !=
nullptr;
648 }
catch (boost::bad_get
const&) {
654 template <typename T, typename std::enable_if_t<std::is_base_of<Storable, T>::value,
int> = 0>
661 auto foo = unsafeLookup(key.
getId());
663 auto pointer = boost::get<std::shared_ptr<Storable>
const&>(foo);
667 return typedPointer.use_count() > 0;
668 }
catch (boost::bad_get
const&) {
676 template <
class Visitor>
677 using _VisitorResult = std::result_of_t<Visitor && (K&&, bool&)>;
681 template <
class Visitor,
typename std::enable_if_t<std::is_
void<_VisitorResult<Visitor>>::value,
int> = 0>
682 void _apply(Visitor&& visitor)
const {
683 for (K
const& key :
keys()) {
684 boost::variant<K> varKey =
key;
685 boost::apply_visitor(visitor, varKey, unsafeLookup(key));
690 template <
class Visitor,
691 typename std::enable_if_t<!std::is_void<_VisitorResult<Visitor>>::value,
int> = 0>
692 auto _apply(Visitor&& visitor)
const {
696 for (K
const& key :
keys()) {
697 boost::variant<K> varKey =
key;
698 results.
emplace_back(boost::apply_visitor(visitor, varKey, unsafeLookup(key)));
704 template <
class Visitor,
typename std::enable_if_t<std::is_
void<_VisitorResult<Visitor>>::value,
int> = 0>
705 void _apply(Visitor&& visitor) {
706 for (K
const& key :
keys()) {
707 boost::variant<K> varKey =
key;
710 boost::apply_visitor(visitor, varKey, ref);
715 template <
class Visitor,
716 typename std::enable_if_t<!std::is_void<_VisitorResult<Visitor>>::value,
int> = 0>
717 auto _apply(Visitor&& visitor) {
721 for (K
const& key :
keys()) {
722 boost::variant<K> varKey =
key;
725 results.
emplace_back(boost::apply_visitor(visitor, varKey, ref));
741 template <
typename K>
754 virtual void clear() noexcept = 0;
774 template <
typename T>
798 template <
typename T>
800 auto strongKey = makeKey<T>(
key);
802 auto result = make_pair(strongKey,
false);
803 result.second = insert(strongKey, value);
820 template <
typename T>
823 return unsafeErase(key.
getId());
842 virtual bool unsafeInsert(K key,
StorableType&& value) = 0;
853 virtual bool unsafeErase(K key) = 0;
861 template <
typename K,
typename V>
862 struct hash<typename
lsst::afw::typehandling::Key<K, V>> {
T is_permutation(T... args)
auto apply(Visitor &&visitor)
Apply a modifying operation to each key-value pair in the map.
size_type count(Key< K, T > const &key) const
Return the number of elements mapped to the specified key.
bool operator!=(GenericMap const &other) const
Test for map equality.
bool erase(Key< K, T > const &key)
Remove the mapping for a key from this map, if it exists.
bool contains(VertexIterator const begin, VertexIterator const end, UnitVector3d const &v)
Container that passes Storable objects by value while preserving type.
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.
T & at(Key< K, T > const &key)
Return a reference to the mapped value of the element with key equal to key.
Interface supporting iteration over heterogenous containers.
constexpr Key< K, V > makeKey(K const &id)
Factory function for Key, to enable type parameter inference.
size_t operator()(argument_type const &obj) const noexcept
decltype(_typeToConstRef(std::declval< StorableType >())) ConstValueReference
A type-agnostic reference to the value stored inside the map.
constexpr bool operator==(Key< K, V > const &other) const noexcept
Test for key equality.
bool contains(Key< K, T > const &key) const
Return true if this map contains a mapping for 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.
boost::variant< bool, std::int32_t, std::int64_t, float, double, std::string, PolymorphicValue, std::shared_ptr< Storable > > StorableType
The types that can be stored in a map.
Key for type-safe lookup in a GenericMap.
virtual ConstValueReference unsafeLookup(K key) const =0
Return a reference to the mapped value of the element with key equal to key.
A base class for image defects.
auto apply(Visitor &&visitor) const
Apply an operation to each key-value pair in the map.
constexpr Key(K id)
Construct a new key.
ValueReference unsafeLookup(K key)
Return a reference to the mapped value of the element with key equal to key.
typename lsst::afw::typehandling::Key< K, V > argument_type
T dynamic_pointer_cast(T... args)
constexpr bool operator!=(Key< K, U > const &other) const noexcept
Test for key equality.
std::size_t hash_value() const noexcept
Return a hash of this object.
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Reports attempts to access elements outside a valid range of indices.
virtual bool operator==(GenericMap const &other) const noexcept
Test for map equality.
decltype(_typeToRef(std::declval< StorableType >())) ValueReference
A type-agnostic reference to the value stored inside the map.
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...
constexpr bool IS_SMART_PTR
ItemVariant const * other
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...
Interface for a GenericMap that allows element addition and removal.
constexpr K const & getId() const noexcept
Return the identifier of this field.
Interface for a heterogeneous map.
Key & operator=(Key const &)=delete
T emplace_back(T... args)