1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
| #include <map>
#include <set>
#include <vector>
#include <string>
#include <iostream>
namespace meta {
struct true_type { static const bool value = true; };
struct false_type { static const bool value = false; };
template<class T, class U> struct is_same : false_type {};
template<class T> struct is_same<T, T> : true_type {};
template<bool, class T, class U> struct conditional { typedef T type; };
template<class T, class U> struct conditional<false, T, U> { typedef U type; };
template<class R, class T> struct cp_const { typedef T type; };
template<class R, class T> struct cp_const<const R &, T> { typedef const T type; };
}
template <class It>
struct _is_map_iterator { // SFINAE value
typedef char yes;
typedef struct {char a[2]; } no;
template <class T> static no is_m_i(...);
template <class T> static
typename meta::conditional<
( meta::is_same<T, typename std::map<typename T::value_type::first_type, typename T::value_type::second_type>::iterator>::value
|| meta::is_same<T, typename std::map<typename T::value_type::first_type, typename T::value_type::second_type>::const_iterator>::value),
yes,
no
>::type is_m_i(typename T::value_type::second_type*);
static const bool value = sizeof(is_m_i<It>(0)) == sizeof(yes); // SFINAE old style
};
template<class It>
struct map_iterator_value {
typedef typename meta::cp_const<typename It::reference, typename It::value_type::second_type>::type type;
};
template <class It, bool> // SFINAE type dérivée
struct is_map_iterator : meta::true_type {
typedef typename map_iterator_value<It>::type iterator_value_type; // gère également type retour
};
template <class It>
struct is_map_iterator<It, false> : meta::false_type {
typedef typename It::reference iterator_value_type;
};
template <class It> // on choisir par surcharge
typename map_iterator_value<It>::type & _iterator_value(It it, meta::true_type) {
return it->second;
}
template <class It>
typename It::reference _iterator_value(It it, meta::false_type) {
return *it;
}
template <class It> // enveloppe au-dessus des surcharges
typename is_map_iterator<It, _is_map_iterator<It>::value>::iterator_value_type & iterator_value(It it) {
return _iterator_value(it, is_map_iterator<It, _is_map_iterator<It>::value>());
}
template<class T>
T const & const_(T const & x) {
return x;
}
template<class T>
struct my_allocator : std::allocator<T>
{
template<class U> struct rebind {
typedef my_allocator<U> other;
};
my_allocator()
{}
template<class Other>
my_allocator(Other const &)
{}
};
int main() {
std::map<int, std::string> mm; mm[0]="bonjour";
std::vector<std::string> mv(1, "au revoir");
std::vector<std::pair<int, std::string> > mp(1, std::make_pair(0, "ok"));
std::set<std::pair<int, std::string> > ms; ms.insert(std::make_pair(0, "ok 2"));
std::map<int, std::string, std::less<int>, my_allocator<std::pair<int, std::string> > > ma; ma[0]="my_allocator";
std::cout << iterator_value(mm.begin()) << std::endl; // bonjour
std::cout << iterator_value(mv.begin()) << std::endl; // au revoir
std::cout << iterator_value(ma.begin()) << std::endl; // my_allocator
std::cout << iterator_value(mp.begin()).second << std::endl; // ok
std::cout << iterator_value(ms.begin()).second << std::endl; // ok 2
std::cout << iterator_value(const_(mm).begin()) << std::endl; // bonjour
std::cout << iterator_value(const_(mv).begin()) << std::endl; // au revoir
std::cout << iterator_value(const_(ma).begin()) << std::endl; // my_allocator
std::cout << iterator_value(const_(mp).begin()).second << std::endl; // ok
std::cout << iterator_value(const_(ms).begin()).second << std::endl; // ok 2
} |
Partager