having an alternate function based on some trait .. exactly how to do?

Discussion in 'C++' started by abir, Mar 28, 2008.

  1. abir

    abir Guest

    HI,
    i have a class like this (simplified version)
    template<typename C>
    class range_view{
    public: /// all of the container typedefs.
    iterator begin(){
    return cont_.begin()+range_.first;
    }
    iterator end(){
    return cont_.begin()+range_.second;
    }
    private:
    C* cont_;
    std::pait<size_type,size_type> range_;
    };

    now i want to handle begin & end different way some container. At
    present i copied it again written as,

    template<typename C, typename M = C::remove_aware>
    class range_view{
    public: /// all of the container typedefs.
    iterator begin(){
    return cont_->begin()+range_.first+cont_->remove_count();
    }
    iterator end(){
    return cont_->begin()+range_.second+cont_->remove_count();
    }
    private:
    C* cont_;
    std::pait<size_type,size_type> range_;
    };
    so, instead of having a full class for a remove aware container, i
    want just begin & end should match with the trait...
    anyways can it be done using SFINAE ?
    thanks
    abir
    abir, Mar 28, 2008
    #1
    1. Advertising

  2. abir

    gnuyuva Guest

    Re: having an alternate function based on some trait .. exactly howto do ?

    On Mar 28, 3:56 pm, abir <> wrote:
    > HI,
    > i have a class like this (simplified version)
    > template<typename C>
    > class range_view{
    > public: /// all of the container typedefs.
    > iterator begin(){
    > return cont_.begin()+range_.first;
    > }
    > iterator end(){
    > return cont_.begin()+range_.second;
    > }
    > private:
    > C* cont_;
    > std::pait<size_type,size_type> range_;
    > };
    >
    > now i want to handle begin & end different way some container. At
    > present i copied it again written as,
    >
    > template<typename C, typename M = C::remove_aware>
    > class range_view{
    > public: /// all of the container typedefs.
    > iterator begin(){
    > return cont_->begin()+range_.first+cont_->remove_count();
    > }
    > iterator end(){
    > return cont_->begin()+range_.second+cont_->remove_count();
    > }
    > private:
    > C* cont_;
    > std::pait<size_type,size_type> range_;
    > };


    First of all, the code you have written is quite confusing. There are
    two definitions for range_view. I don't think that the second one is a
    specialization. Apart from this: "cont_->begin() + range_.first" is
    only valid for basic arrays or std::vector (if we assume that all the
    values are contiguous in the memory and it is always!).

    > so, instead of having a full class for a remove aware container, i
    > want just begin & end should match with the trait...
    > anyways can it be done using SFINAE ?


    For me (from what i have got from your code), its enough if you
    specialize begin() and end() functions. Its better if you post some
    more code.

    > thanks
    > abir
    gnuyuva, Mar 28, 2008
    #2
    1. Advertising

  3. abir

    abir Guest

    Re: having an alternate function based on some trait .. exactly howto do ?

    On Mar 28, 4:48 pm, gnuyuva <> wrote:
    > On Mar 28, 3:56 pm, abir <> wrote:
    >
    >
    >
    > > HI,
    > > i have a class like this (simplified version)
    > > template<typename C>
    > > class range_view{
    > > public: /// all of the container typedefs.
    > > iterator begin(){
    > > return cont_.begin()+range_.first;
    > > }
    > > iterator end(){
    > > return cont_.begin()+range_.second;
    > > }
    > > private:
    > > C* cont_;
    > > std::pait<size_type,size_type> range_;
    > > };

    >
    > > now i want to handle begin & end different way some container. At
    > > present i copied it again written as,

    >
    > > template<typename C, typename M = C::remove_aware>
    > > class range_view{
    > > public: /// all of the container typedefs.
    > > iterator begin(){
    > > return cont_->begin()+range_.first+cont_->remove_count();
    > > }
    > > iterator end(){
    > > return cont_->begin()+range_.second+cont_->remove_count();
    > > }
    > > private:
    > > C* cont_;
    > > std::pait<size_type,size_type> range_;
    > > };

    >
    > First of all, the code you have written is quite confusing. There are
    > two definitions for range_view. I don't think that the second one is a
    > specialization. Apart from this: "cont_->begin() + range_.first" is
    > only valid for basic arrays or std::vector (if we assume that all the
    > values are contiguous in the memory and it is always!).
    >
    > > so, instead of having a full class for a remove aware container, i
    > > want just begin & end should match with the trait...
    > > anyways can it be done using SFINAE ?

    >
    > For me (from what i have got from your code), its enough if you
    > specialize begin() and end() functions. Its better if you post some
    > more code.
    >
    > > thanks
    > > abir

    Ok, i am giving a full so far working example (just working one ....
    not complete in its description. esp the reorient_iterator class which
    is nearly same as boost permutation_iterator). the range_view (or
    actually the class was reorient_view) works ONLY on random access
    container ... but not necessarily a contiguous memory one (including
    range_view, they can work with deque or some other container also)
    CODE: (little long to make it a workable code)
    Here what i want is that reorient_view and its specialization should
    be a single implementation, where begin & end (a few other) will be
    specialized for memorable tag ... , rather than the whole class
    specialization
    template<typename T>
    class memory_vector{
    private:
    typedef std::deque<T> cont_t;
    struct is_memorable : public boost::true_type{};
    public:
    typedef typename cont_t::value_type value_type;
    typedef typename cont_t::size_type size_type;
    typedef typename cont_t::iterator iterator;
    typedef typename cont_t::const_iterator const_iterator;
    typedef typename cont_t::reverse_iterator reverse_iterator;
    typedef typename cont_t::const_reverse_iterator
    const_reverse_iterator;
    typedef typename cont_t::reference reference;
    typedef typename cont_t::const_reference const_reference;
    typedef typename cont_t::pointer pointer;
    typedef typename cont_t::const_pointer const_pointer;
    typedef typename cont_t::difference_type difference_type;
    typedef is_memorable memorable;
    private:
    size_type remove_count_;
    cont_t cont_;
    public:
    memory_vector() : cont_(),remove_count_(0){}
    template<typename C>
    memory_vector(const C& c) : remove_count_(0){
    typename C::const_iterator it = c.begin();
    typename C::const_iterator end = c.end();
    for(; it!= end; ++it) cont_.push_back(*it);
    }
    iterator begin(){ return cont_.begin(); }
    iterator end(){ return cont_.end();}
    reverse_iterator rbegin() { return cont_.rbegin();}
    reverse_iterator rend(){ return cont_.rend();}
    const_iterator begin()const{ return cont_.begin();}
    const_iterator end()const{ return cont_.end();}
    const_reverse_iterator rbegin()const{ return cont_.rbegin();}
    const_reverse_iterator rend()const{ return cont_.rend();}
    void push_back(const value_type& v){
    cont_.push_back(v);
    }
    void pop_front(){
    cont_.pop_front();
    ++remove_count_;
    }
    size_type remove_count()const{ return remove_count_;}
    };
    template<typename ElemIter,typename IndexIter>
    class reorient_iterator : public ElemIter{
    public:
    typedef typename ElemIter::iterator_category iterator_category;
    typedef typename ElemIter::value_type value_type;
    typedef typename ElemIter::reference reference;
    typedef typename ElemIter::pointer pointer;
    typedef reorient_iterator<ElemIter,IndexIter> self_type;
    //typedef typename T::size_type size_type;
    public:
    reorient_iterator(ElemIter it,IndexIter pos) : it_(it),pos_(pos){}
    self_type& operator++(){
    ++pos_;
    return *this;
    }
    self_type operator++(int){
    self_type tmp(*this);
    pos++;
    return tmp;
    }
    self_type& operator--(){
    --pos_;
    return *this;
    }
    reference operator*(){
    return *(it_+*pos_);
    }
    pointer operator->(){
    return it_+*pos_;
    }
    bool operator!= (const self_type& other){
    return it_+*pos_ != other.it_+ *other.pos_;
    }
    private:
    ElemIter it_;
    IndexIter pos_;
    };
    template<class ElemIterT, class IndexIterT>
    inline reorient_iterator<ElemIterT,IndexIterT>
    make_reorient_iterator(ElemIterT eit, IndexIterT iit){
    typedef reorient_iterator<ElemIterT,IndexIterT> result_t;
    return result_t(eit,iit);
    }
    template<typename C,typename Enable = void>
    class reorient_view{
    public:
    typedef reorient_view<C,Enable> self_type;
    typedef typename C::value_type value_type;
    typedef typename C::size_type size_type;
    typedef typename C::reference reference;
    typedef typename C::pointer pointer;
    typedef typename C::const_reference const_reference;
    typedef typename C::const_pointer const_pointer;
    typedef std::vector<size_type> index_t;
    typedef reorient_iterator<typename C::iterator,
    typename index_t::iterator > iterator;
    typedef reorient_iterator<typename C::const_iterator,
    typename index_t::iterator> const_iterator;
    typedef std::reverse_iterator<iterator> reverse_iterator;
    template<typename I>
    reorient_view(C& cont,const I& index) :cont_(&cont){
    typename I::const_iterator it = index.begin();
    typename I::const_iterator end = index.end();
    for(;it!=end; ++it){
    index_.push_back(*it);
    }
    }
    iterator begin(){
    return make_reorient_iterator(cont_->begin(),index_.begin());
    }
    iterator end(){
    return make_reorient_iterator(cont_->begin(),index_.end());
    }
    reverse_iterator rbegin(){
    return std::reverse_iterator<iterator>(rend());
    }
    reverse_iterator rend(){
    return std::reverse_iterator<iterator>(rbegin());
    }
    private:
    index_t index_;
    C* cont_;
    };
    template<typename C>
    class reorient_view<C, typename boost::enable_if<typename
    C::is_memorable>::type >{
    public:
    typedef typename C::value_type value_type;
    typedef typename C::size_type size_type;
    typedef typename C::reference reference;
    typedef typename C::pointer pointer;
    typedef typename C::const_reference const_reference;
    typedef typename C::const_pointer const_pointer;
    typedef std::vector<size_type> index_t;
    typedef reorient_iterator<typename C::iterator,
    typename index_t::iterator > iterator;
    typedef reorient_iterator<typename C::const_iterator,
    typename index_t::iterator> const_iterator;
    typedef std::reverse_iterator<iterator> reverse_iterator;
    public:
    template<typename I>
    reorient_view(C& cont,const I& index) :cont_(&cont){
    typename I::const_iterator it = index.begin();
    typename I::const_iterator end = index.end();
    for(;it!=end; ++it){
    index_.push_back(*it);
    }
    }
    iterator begin(){
    return make_reorient_iterator(cont_->begin()-cont_-
    >remove_count(),index_.begin());

    }
    iterator end(){
    return make_reorient_iterator(cont_->begin()-cont_-
    >remove_count(),index_.end());

    }
    reverse_iterator rbegin(){
    return std::reverse_iterator<iterator>(rend());
    }
    reverse_iterator rend(){
    return std::reverse_iterator<iterator>(rbegin());
    }
    private:
    index_t index_;
    C* cont_;
    };
    int main(){///test
    using namespace std;
    using namespace boost::assign;
    using namespace boost::lambda;
    deque<int> v;
    v+=0,10,20,30,40,50,60,70,80,90;
    memory_vector<int> mv = v;
    vector<std::size_t> iv;
    iv+=1,3,6,7,8;
    typedef reorient_view<memory_vector<int> > MIVIEW;
    typedef reorient_view<deque<int> > IVIEW;
    IVIEW view(v,iv);
    MIVIEW mview(mv,iv);
    cout<<"v: "; for_each(v.begin(),v.end(),cout<<_1<<" "); cout<<endl;
    cout<<"rev v:";for_each(v.rbegin(),v.rend(),cout<<_1<<" ");
    cout<<endl;
    cout<<"iv: ";for_each(iv.begin(),iv.end(),cout<<_1<<" ");cout<<endl;
    cout<<"mv: ";for_each(mv.begin(),mv.end(),cout<<_1<<" ");cout<<endl;
    cout<<"rev mv: ";for_each(mv.rbegin(),mv.rend(),cout<<_1<<"
    ");cout<<endl;
    cout<<"view: ";for_each(view.begin(),view.end(),std::cout<<_1<<" ");
    cout<<endl;
    cout<<"mview: ";for_each(mview.begin(),mview.end(),std::cout<<_1<<"
    "); cout<<endl;
    mv.pop_front(); v.pop_front();
    cout<<"view: ";for_each(view.begin(),view.end(),std::cout<<_1<<" ");
    cout<<endl;
    cout<<"mview: ";for_each(mview.begin(),mview.end(),std::cout<<_1<<"
    "); cout<<endl;
    //cout<<"rev view:
    ";for_each(view.rbegin(),view.rend(),std::cout<<_1<<" "); cout<<endl;
    std::system("PAUSE");
    }

    thanks
    abir, Mar 28, 2008
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Patrick Guio

    trait technique?

    Patrick Guio, Dec 18, 2004, in forum: C++
    Replies:
    7
    Views:
    368
    Jonathan Mcdougall
    Dec 21, 2004
  2. Chris
    Replies:
    2
    Views:
    677
    Chris
    Mar 4, 2007
  3. abir
    Replies:
    3
    Views:
    335
    Triple-DES
    Feb 27, 2008
  4. Replies:
    10
    Views:
    336
    Sean O'Halpin
    Jul 17, 2006
  5. Thufir
    Replies:
    2
    Views:
    93
    Thufir
    Nov 13, 2007
Loading...

Share This Page