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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
#include <iostream>
#include <stdlib.h>
#include <vector>
#include <forward_list>
#include <optional>
template<typename T, typename = decltype(std::declval<T>().rbegin(),true)>
constexpr bool has_reverse_iterator(int x)
{return true ;}
template<typename T>
constexpr bool has_reverse_iterator(double x)
{return false;}
template<typename T>
constexpr bool has_reverse_iterator()
{return has_reverse_iterator<T>(1) ;}
/////////////////////////////////////////////////////////////////////
/////////////////// wrapper
/////////////////////////////////////////////////////////////////////
template< class C >
class wrapper{
typedef decltype(*(std::declval<C>().begin())) R;
typedef typename std::remove_reference<R>::type V;
std::vector<V*> collection;
typedef decltype(collection.begin()) iteratorbase;
typedef decltype(collection.rbegin()) riteratorbase;
public:
class iterator:public iteratorbase{
public:
iterator(iteratorbase iter):iteratorbase(iter){}
R& operator*() {
iteratorbase & ib = * this;
return(* * ib);}
};
class riterator:public riteratorbase{
public:
riterator(riteratorbase iter):riteratorbase(iter){}
R& operator*() {
riteratorbase & ib = * this;
return(* * ib); }
};
iterator begin(){ return iterator(collection.begin());}
iterator end(){ return iterator(collection.end());}
riterator rbegin(){ return riterator(collection.rbegin());}
riterator rend(){ return riterator(collection.rend());}
wrapper( C & v){
for(auto& x : v){collection.push_back( &x);}
}
};
template<typename T>
wrapper<T> make_wrapper(T& v){
return wrapper<T>(v);
}
/////////////////////////////////////////////////////////////////////
/////////////////// reverser
/////////////////////////////////////////////////////////////////////
template<class C ,int X>
class reverser;
template<class C>
class reverser<C,1> {
public:
protected:
C& collection;
typedef decltype(collection.rbegin()) iterator;
typedef decltype(*collection.rbegin()) R;
public:
iterator begin(){return collection.rbegin();}
iterator end(){ return collection.rend();}
reverser( C & v): collection(v){}
};
template< class C >
class reverser<C,2> : public reverser<wrapper<C>,1>{
wrapper<C> rtype;
std::optional<wrapper<C>> _collection;
public:
reverser( C & v):_collection(std::move(make_wrapper(v))),
reverser<wrapper<C>,1>::reverser(* _collection) {} //<-- this initializer doesn't resolve.
};
template<typename T,typename std::enable_if<! has_reverse_iterator<T>(),std::nullptr_t>::type = nullptr>
reverser<T,2> make_reverser(T & v){
return reverser<T,2>(v);
}
template<typename T,typename std::enable_if<has_reverse_iterator<T>(),std::nullptr_t>::type = nullptr>
reverser<T,1> make_reverser(T & v){
return reverser<T,1>(v);
}
/////////////////////////////////////////////////////////////////////
/////////////////// main
/////////////////////////////////////////////////////////////////////
int main(){
////// the case when the base object has a reverse iterator is fine.
std::vector<int> v {1,2,3,4,5,6,7,8} ;
auto rv = make_reverser(v); //<--- this works
for(auto i:rv){std::cout<<i<<std::endl;}
////// the case when the base object doesn't have a reverse iterator doesn't compile
std::forward_list<int> f {1,2,3,4,5,6,7,8} ;
auto rf = make_reverser(f); //<--- this doesn't compile
for(auto i:rf){std::cout<<i<<std::endl;}
}
|