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>
 
  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>
 
  422     T 
const& _at(Key<K, T> 
const& 
key)
 const {
 
  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.";
 
  435                 throw LSST_EXCEPT(pex::exceptions::OutOfRangeError, message.
str());
 
  437         } 
catch (boost::bad_get 
const&) {
 
  439             message << 
"Key " << 
key << 
" not found, but a key labeled " << 
key.getId() << 
" is present.";
 
  440             throw LSST_EXCEPT(pex::exceptions::OutOfRangeError, message.
str());
 
  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.";
 
  464                 throw LSST_EXCEPT(pex::exceptions::OutOfRangeError, message.
str());
 
  466         } 
catch (boost::bad_get 
const&) {
 
  468             message << 
"Key " << 
key << 
" not found, but a key labeled " << 
key.getId() << 
" is present.";
 
  469             throw LSST_EXCEPT(pex::exceptions::OutOfRangeError, message.
str());
 
  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 {
 
  548             boost::variant<K> varKey = 
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 {
 
  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) {
 
  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) {
 
  586             boost::variant<K> varKey = 
key;
 
  589             results.
emplace_back(boost::apply_visitor(visitor, varKey, ref));
 
  605 template <
typename K>
 
  638     template <typename T>
 
  662     template <
typename T>
 
  664         auto strongKey = makeKey<T>(
key);
 
  666         auto result = make_pair(strongKey, 
false);
 
  684     template <
typename T>