Il test risposte esistente per le proprietà molto specifiche di std::map
, o che è proprio una specializzazione di std::map
(che sarebbe falsa per std::unordered_map
o tipi non standard con la stessa interfaccia di std::map
), o testare che il suo value_type
è esattamente std::pair<const key_type, mapped_type>
(che sarebbe vero per multimap
e unordered_map
, ma falso per tipi non standard con interfacce simili).
Ciò solo prove che essa fornisce key_type
e mapped_type
membri, e si può accedere con operator[]
, quindi non dire che è std::multimap
mappish:
#include <type_traits>
namespace detail {
// Needed for some older versions of GCC
template<typename...>
struct voider { using type = void; };
// std::void_t will be part of C++17, but until then define it ourselves:
template<typename... T>
using void_t = typename voider<T...>::type;
template<typename T, typename U = void>
struct is_mappish_impl : std::false_type { };
template<typename T>
struct is_mappish_impl<T, void_t<typename T::key_type,
typename T::mapped_type,
decltype(std::declval<T&>()[std::declval<const typename T::key_type&>()])>>
: std::true_type { };
}
template<typename T>
struct is_mappish : detail::is_mappish_impl<T>::type { };
Poiché is_mappish
ha una "base caratteristica" di uno true_type
o false_type
è possibile inviare su di esso in questo modo:
template <typename T>
auto foo(const T& items, true_type)
{
// here be maps
}
template <typename T>
auto foo(const T& items, false_type)
{
// map-free zone
}
template <typename T>
auto foo(const T& items)
{
return foo(items, is_mappish<T>{});
}
oppure si può evitare di dispacciamento del tutto, e solo il sovraccarico foo
per le mappe e non-mappe:
template <typename T,
std::enable_if_t<is_mappish<T>{}, int> = 0>
auto foo(const T& items)
{
// here be maps
}
template <typename T,
std::enable_if_t<!is_mappish<T>{}, int> = 0>
auto foo(const T& items)
{
// map-free zone
}
fonte
2016-02-09 13:59:35
controllare se essa è annidato 'key_type' e' tipi mapped_type'? –