25 #ifndef LSST_AFW_TYPEHANDLING_GENERICMAP_H 26 #define LSST_AFW_TYPEHANDLING_GENERICMAP_H 32 #include <type_traits> 36 #include "boost/variant.hpp" 46 namespace typehandling {
107 template <typename
T, typename
std::enable_if_t<!detail::
IS_SMART_PTR<T>,
int> = 0>
110 return const_cast<T&
>(
static_cast<const GenericMap&
>(*this).
at(key));
113 template <
typename T,
typename std::enable_if_t<!detail::IS_SMART_PTR<T>,
int> = 0>
119 template <typename T, typename std::enable_if_t<std::is_base_of<Storable, T>::value,
int> = 0>
131 virtual bool empty()
const noexcept = 0;
155 template <
typename T>
192 template <
typename T>
195 return _contains(key);
229 auto keys1 = this->
keys();
230 auto keys2 =
other.keys();
234 for (K
const& key : keys1) {
305 template <
class Visitor>
306 auto apply(Visitor&& visitor)
const {
308 return _apply(visitor);
327 template <
class Visitor>
330 return _apply(visitor);
341 template <
typename... Types>
342 static boost::variant<std::add_lvalue_reference_t<Types>...> _typeToRef(
343 boost::variant<Types...>
const&) noexcept;
344 template <
typename... Types>
345 static boost::variant<std::add_lvalue_reference_t<std::add_const_t<Types>>...> _typeToConstRef(
346 boost::variant<Types...>
const&) noexcept;
392 using NonConstRef = std::add_lvalue_reference_t<
393 std::remove_const_t<std::remove_reference_t<decltype(value)>>>;
395 return const_cast<NonConstRef
>(value);
397 return boost::apply_visitor(removeConst, constRef);
404 template <
typename T,
405 typename std::enable_if_t<
409 "Due to implementation constraints, const keys are not supported.");
412 return boost::get<T const&>(foo);
413 }
catch (boost::bad_get
const&) {
415 message <<
"Key " << key <<
" not found, but a key labeled " << key.
getId() <<
" is present.";
421 template <typename T, typename std::enable_if_t<std::is_base_of<Storable, T>::value,
int> = 0>
424 "Due to implementation constraints, const keys are not supported.");
428 Storable const& value = boost::get<PolymorphicValue const&>(foo);
429 T const* typedPointer =
dynamic_cast<T const*
>(&value);
430 if (typedPointer !=
nullptr) {
431 return *typedPointer;
434 message <<
"Key " << key <<
" not found, but a key labeled " << key.
getId() <<
" is present.";
437 }
catch (boost::bad_get
const&) {
439 message <<
"Key " << key <<
" not found, but a key labeled " << key.
getId() <<
" is present.";
445 template <typename T, typename std::enable_if_t<std::is_base_of<Storable, T>::value,
int> = 0>
448 "Due to implementation constraints, pointers to non-const are not supported.");
451 auto pointer = boost::get<std::shared_ptr<Storable const>
const&>(foo);
452 if (pointer ==
nullptr) {
459 if (typedPointer.use_count() > 0) {
463 message <<
"Key " << key <<
" not found, but a key labeled " << key.
getId() <<
" is present.";
466 }
catch (boost::bad_get
const&) {
468 message <<
"Key " << key <<
" not found, but a key labeled " << key.
getId() <<
" is present.";
474 template <
typename T,
475 typename std::enable_if_t<
477 bool _contains(
Key<K, T> const& key)
const {
486 boost::get<T const&>(foo);
488 }
catch (boost::bad_get
const&) {
494 template <typename T, typename std::enable_if_t<std::is_base_of<Storable, T>::value,
int> = 0>
495 bool _contains(
Key<K, T> const& key)
const {
504 Storable const& value = boost::get<PolymorphicValue const&>(foo);
505 auto asT =
dynamic_cast<T const*
>(&value);
506 return asT !=
nullptr;
507 }
catch (boost::bad_get
const&) {
513 template <typename T, typename std::enable_if_t<std::is_base_of<Storable, T>::value,
int> = 0>
516 "Due to implementation constraints, pointers to non-const are not supported.");
524 auto pointer = boost::get<std::shared_ptr<Storable const>
const&>(foo);
525 if (pointer ==
nullptr) {
531 return typedPointer.use_count() > 0;
532 }
catch (boost::bad_get
const&) {
540 template <
class Visitor>
541 using _VisitorResult = std::result_of_t<Visitor && (K&&, bool&)>;
545 template <
class Visitor,
typename std::enable_if_t<std::is_
void<_VisitorResult<Visitor>>::value,
int> = 0>
546 void _apply(Visitor&& visitor)
const {
547 for (K
const& key :
keys()) {
548 boost::variant<K> varKey =
key;
549 boost::apply_visitor(visitor, varKey,
unsafeLookup(key));
554 template <
class Visitor,
555 typename std::enable_if_t<!std::is_void<_VisitorResult<Visitor>>::value,
int> = 0>
556 auto _apply(Visitor&& visitor)
const {
560 for (K
const& key :
keys()) {
561 boost::variant<K> varKey =
key;
568 template <
class Visitor,
typename std::enable_if_t<std::is_
void<_VisitorResult<Visitor>>::value,
int> = 0>
569 void _apply(Visitor&& visitor) {
570 for (K
const& key :
keys()) {
571 boost::variant<K> varKey =
key;
574 boost::apply_visitor(visitor, varKey, ref);
579 template <
class Visitor,
580 typename std::enable_if_t<!std::is_void<_VisitorResult<Visitor>>::value,
int> = 0>
581 auto _apply(Visitor&& visitor) {
585 for (K
const& key :
keys()) {
586 boost::variant<K> varKey =
key;
589 results.
emplace_back(boost::apply_visitor(visitor, varKey, ref));
605 template <
typename K>
618 virtual void clear() noexcept = 0;
638 template <
typename T>
662 template <
typename T>
664 auto strongKey = makeKey<T>(
key);
666 auto result = make_pair(strongKey,
false);
667 result.second = insert(strongKey, value);
684 template <
typename T>
687 return unsafeErase(key.
getId());
706 virtual bool unsafeInsert(K key,
StorableType&& value) = 0;
717 virtual bool unsafeErase(K key) = 0;
T is_permutation(T... args)
auto apply(Visitor &&visitor)
Apply a modifying operation to each key-value pair in the map.
boost::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.
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.
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.
decltype(_typeToConstRef(std::declval< StorableType >())) ConstValueReference
A type-agnostic reference to the value stored inside the map.
virtual size_type size() const noexcept=0
Return the number of key-value pairs in the map.
bool contains(Key< K, T > const &key) const
Return true if this map contains a mapping for the specified key.
ItemVariant const * other
T const & at(Key< K, T > const &key) const
Return a reference to the mapped value of the element with key equal to key.
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.
ValueReference unsafeLookup(K key)
Return a reference to the mapped value of the element with key equal to key.
T dynamic_pointer_cast(T... args)
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...
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Reports attempts to access elements outside a valid range of indices.
virtual bool contains(K const &key) const =0
Return true if this map contains a mapping whose key has the specified label.
virtual ~GenericMap() noexcept=default
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.
constexpr bool IS_SMART_PTR
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...
virtual bool empty() const noexcept=0
Return true if this map contains no key-value pairs.
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.
T emplace_back(T... args)
virtual std::vector< K > const & keys() const noexcept=0
Return the set of all keys, without type information.