matching multiple template

Discussion in 'C++' started by abir, Jul 8, 2008.

  1. abir

    abir Guest

    i have a template
    template<typename S> class Indexer{};
    i want to have a specialization for std::vector both const & non const
    version.
    template<typename T,typename A> class Indexer<std::vector<T,A> > {}
    matches only with nonconst version. anyway to match it for both? and
    get if it is const or nonconst?

    Actually i want 2 specialization, one for std::vector<T,A> const & non
    const other for std::deque<T,A> const & non const.

    thanks
    abir
     
    abir, Jul 8, 2008
    #1
    1. Advertising

  2. abir

    Eric Pruneau Guest

    "abir" <> a écrit dans le message de news:
    ...
    >i have a template
    > template<typename S> class Indexer{};
    > i want to have a specialization for std::vector both const & non const
    > version.
    > template<typename T,typename A> class Indexer<std::vector<T,A> > {}
    > matches only with nonconst version. anyway to match it for both? and
    > get if it is const or nonconst?
    >
    > Actually i want 2 specialization, one for std::vector<T,A> const & non
    > const other for std::deque<T,A> const & non const.
    >
    > thanks
    > abir


    I'm not sure if I understand what you really want to do but here is what I
    think.

    you have a class

    template<typename S>
    class Indexer{ };

    and you want to specialize this class when S is a vector and when S is a
    const vector (samething with deque).

    Here is how to do that. Note that I've removed the allocator template
    parameter to simplify the example but I amsure you will find a way to
    integrate it!!!


    template<typename T, typename CONT>
    struct Indexer
    {
    Indexer() { cout <<"1\n"; }
    };

    template<typename T>
    struct Indexer<T, vector<T> >
    {
    Indexer() { cout <<"2\n"; }
    };

    template<typename T>
    struct Indexer<T, const vector<T> >
    {
    Indexer() { cout <<"3\n"; }
    };

    template<typename T>
    struct Indexer<T, deque<T> >
    {
    Indexer() { cout <<"4\n"; }
    };

    template<typename T>
    struct Indexer<T, const deque<T> >
    {
    Indexer() { cout <<"5\n"; }
    };


    int main()
    {
    Indexer<int, vector<int> > a; // print 2
    Indexer<int, deque<int> > b; // print 4
    Indexer<int, vector<int> const > c; // print 3
    Indexer<int, deque<int> const > d; // print 5

    return 0;
    }

    ------------------------

    Eric Pruneau
     
    Eric Pruneau, Jul 9, 2008
    #2
    1. Advertising

  3. abir

    abir Guest

    On Jul 9, 6:37 am, "Eric Pruneau" <> wrote:
    > "abir" <> a écrit dans le message de news:
    > ...
    >
    > >i have atemplate
    > >template<typename S> class Indexer{};
    > > i want to have a specialization for std::vector bothconst&nonconst
    > > version.
    > >template<typename T,typename A> class Indexer<std::vector<T,A> > {}
    > > matches only with nonconst version. anyway to match it for both? and
    > > get if it isconstor nonconst?

    >
    > > Actually i want 2 specialization, one for std::vector<T,A>const&non
    > >constother for std::deque<T,A>const&nonconst.

    >
    > > thanks
    > > abir

    >
    > I'm not sure if I understand what you really want to do but here is what I
    > think.
    >
    > you have a class
    >
    > template<typename S>
    > class Indexer{ };
    >
    > and you want to specialize this class when S is a vector and when S is aconstvector (samething with deque).
    >
    > Here is how to do that. Note that I've removed the allocatortemplate
    > parameter to simplify the example but I amsure you will find a way to
    > integrate it!!!
    >
    > template<typename T, typename CONT>
    > struct Indexer
    > {
    > Indexer() { cout <<"1\n"; }
    >
    > };
    >
    > template<typename T>
    > struct Indexer<T, vector<T> >
    > {
    > Indexer() { cout <<"2\n"; }
    >
    > };
    >
    > template<typename T>
    > struct Indexer<T,constvector<T> >
    > {
    > Indexer() { cout <<"3\n"; }
    >
    > };
    >
    > template<typename T>
    > struct Indexer<T, deque<T> >
    > {
    > Indexer() { cout <<"4\n"; }
    >
    > };
    >
    > template<typename T>
    > struct Indexer<T,constdeque<T> >
    > {
    > Indexer() { cout <<"5\n"; }
    >
    > };
    >
    > int main()
    > {
    > Indexer<int, vector<int> > a; // print 2
    > Indexer<int, deque<int> > b; // print 4
    > Indexer<int, vector<int>const> c; // print 3
    > Indexer<int, deque<int>const> d; // print 5
    >
    > return 0;
    >
    > }
    >
    > ------------------------
    >
    > Eric Pruneau


    Thanks for answering.
    Actually this is what i have already. What i want is to match both
    const & non const version in same specialization something like (this
    is not a valid syntax of course),
    template<typename T>
    struct Indexer<T,const vector<T> | vector<T> >
    {
    Indexer() { cout <<"3\n"; }

    };
    so i want both the match to succeed in same specialization. Also i
    need to know which match is there.
    i don't know if it is directly possible, but i am thinking having a
    proxy class to delegate the responsibility.

    thanks
    abir
     
    abir, Jul 9, 2008
    #3
  4. abir

    Eric Pruneau Guest

    [...]

    >> ------------------------
    >>
    >> Eric Pruneau

    >
    >Thanks for answering.
    >Actually this is what i have already. What i want is to match both
    >const & non const version in same specialization something like (this
    >is not a valid syntax of course),
    >template<typename T>
    > struct Indexer<T,const vector<T> | vector<T> >
    > {
    > Indexer() { cout <<"3\n"; }
    >
    > };
    >so i want both the match to succeed in same specialization. Also i
    >need to know which match is there.
    >i don't know if it is directly possible, but i am thinking having a0
    >proxy class to delegate the responsibility.
    >
    >thanks
    >abir


    Ok you leave me no choice but to use the big guns!!!

    here is a solution using boost type triats and enable_if

    template<typename T, typename CONT, typename enable=void>
    struct Indexer
    {
    Indexer() { cout <<"1\n"; }
    };

    // this one could be a bit scary....

    template<typename T, typename CONT>
    struct Indexer<T, CONT, typename boost::enable_if_c<boost::is_same<
    typename boost::add_const<CONT>::type , const vector<T> >::value>::type
    >

    {
    Indexer() { cout <<"2\n"; }
    };


    int main()
    {
    Indexer<int, vector<int> > a; // print 2
    Indexer<int, const vector<int> > b; // guess what? it prints 2 !!!
    Indexer<int, deque<int> > c; // print 1
    return 0;
    }

    ok here is the trick

    add_const<CONT>::type just add a const before CONT if CONT is not already
    const. it does nothing if CONT is already const.

    then we do:
    is_same<const CONT, const vector<T> >::value
    this returns true if const CONT = const vector<T>

    finally enable_if_c has 2 template parameter (the second is void by default)
    The first one must be a bool
    enable_if_c<true>::type return void
    enable_if_c<false>::type is an error

    so if
    is_same<const CONT, const vector<T> >::value
    returns true we got a match and the second template Indexer is used.
    if const CONT is not a const vector then the first template Indexer is used.

    you can find the boost library here www.boost.org
    It is a must . If you don't have it, get it!

    -------------------------

    Eric Pruneau
     
    Eric Pruneau, Jul 10, 2008
    #4
  5. abir

    abir Guest

    On Jul 10, 7:25 am, "Eric Pruneau" <> wrote:
    > [...]
    >
    >
    >
    > >> ------------------------

    >
    > >> Eric Pruneau

    >
    > >Thanks for answering.
    > >Actually this is what i have already. What i want is to match both
    > >const & non const version in same specialization something like (this
    > >is not a valid syntax of course),
    > >template<typename T>
    > > struct Indexer<T,const vector<T> | vector<T> >
    > > {
    > > Indexer() { cout <<"3\n"; }

    >
    > > };
    > >so i want both the match to succeed in same specialization. Also i
    > >need to know which match is there.
    > >i don't know if it is directly possible, but i am thinking having a0
    > >proxy class to delegate the responsibility.

    >
    > >thanks
    > >abir

    >
    > Ok you leave me no choice but to use the big guns!!!
    >
    > here is a solution using boost type triats and enable_if
    >
    > template<typename T, typename CONT, typename enable=void>
    > struct Indexer
    > {
    > Indexer() { cout <<"1\n"; }
    >
    > };
    >
    > // this one could be a bit scary....
    >
    > template<typename T, typename CONT>
    > struct Indexer<T, CONT, typename boost::enable_if_c<boost::is_same<
    > typename boost::add_const<CONT>::type , const vector<T> >::value>::type
    > >

    > {
    > Indexer() { cout <<"2\n"; }
    >
    > };
    >
    > int main()
    > {
    > Indexer<int, vector<int> > a; // print 2
    > Indexer<int, const vector<int> > b; // guess what? it prints 2 !!!
    > Indexer<int, deque<int> > c; // print 1
    > return 0;
    >
    > }
    >
    > ok here is the trick
    >
    > add_const<CONT>::type just add a const before CONT if CONT is not already
    > const. it does nothing if CONT is already const.
    >
    > then we do:
    > is_same<const CONT, const vector<T> >::value
    > this returns true if const CONT = const vector<T>
    >
    > finally enable_if_c has 2 template parameter (the second is void by default)
    > The first one must be a bool
    > enable_if_c<true>::type return void
    > enable_if_c<false>::type is an error
    >
    > so if
    > is_same<const CONT, const vector<T> >::value
    > returns true we got a match and the second template Indexer is used.
    > if const CONT is not a const vector then the first template Indexer is used.
    >
    > you can find the boost library here www.boost.org
    > It is a must . If you don't have it, get it!
    >
    > -------------------------
    >
    > Eric Pruneau


    This is nearly what i wanted. But with a little difference. like this
    one.
    int main()
    {
    Indexer<vector<int> > a; // print 2
    Indexer<const vector<int> > b; // guess what? it prints 2 !!!
    Indexer<deque<int> > c; // print 1
    return 0;
    }
    i.e without the first int (and the alloc param if any). otherwise it
    is fine to me.
    i use boost & tr1 so know enable_if & remove_const etc.
    can is_same compare templates rather than types ? then i can pass the
    first arg as template <typename T,typename A> class S and make
    comparison with std::vector ? Or can i put T at last to meke auto
    deduction of type T without specifying it?

    thanks for answering
    abir


    Thanks for reply. I was unable to see my post for long hours, so i had
    posted the same once again, in this thread
    http://groups.google.com/group/comp...99/fb1ca1a6f5ae69b5?lnk=raot#fb1ca1a6f5ae69b5
    where i explained my intension also.
     
    abir, Jul 10, 2008
    #5
  6. abir

    abir Guest

    On Jul 10, 7:25 am, "Eric Pruneau" <> wrote:
    > [...]
    >
    >
    >
    > >> ------------------------

    >
    > >> Eric Pruneau

    >
    > >Thanks for answering.
    > >Actually this is what i have already. What i want is to match both
    > >const & non const version in same specialization something like (this
    > >is not a valid syntax of course),
    > >template<typename T>
    > > struct Indexer<T,const vector<T> | vector<T> >
    > > {
    > > Indexer() { cout <<"3\n"; }

    >
    > > };
    > >so i want both the match to succeed in same specialization. Also i
    > >need to know which match is there.
    > >i don't know if it is directly possible, but i am thinking having a0
    > >proxy class to delegate the responsibility.

    >
    > >thanks
    > >abir

    >
    > Ok you leave me no choice but to use the big guns!!!
    >
    > here is a solution using boost type triats and enable_if
    >
    > template<typename T, typename CONT, typename enable=void>
    > struct Indexer
    > {
    > Indexer() { cout <<"1\n"; }
    >
    > };
    >
    > // this one could be a bit scary....
    >
    > template<typename T, typename CONT>
    > struct Indexer<T, CONT, typename boost::enable_if_c<boost::is_same<
    > typename boost::add_const<CONT>::type , const vector<T> >::value>::type
    > >

    > {
    > Indexer() { cout <<"2\n"; }
    >
    > };
    >
    > int main()
    > {
    > Indexer<int, vector<int> > a; // print 2
    > Indexer<int, const vector<int> > b; // guess what? it prints 2 !!!
    > Indexer<int, deque<int> > c; // print 1
    > return 0;
    >
    > }
    >
    > ok here is the trick
    >
    > add_const<CONT>::type just add a const before CONT if CONT is not already
    > const. it does nothing if CONT is already const.
    >
    > then we do:
    > is_same<const CONT, const vector<T> >::value
    > this returns true if const CONT = const vector<T>
    >
    > finally enable_if_c has 2 template parameter (the second is void by default)
    > The first one must be a bool
    > enable_if_c<true>::type return void
    > enable_if_c<false>::type is an error
    >
    > so if
    > is_same<const CONT, const vector<T> >::value
    > returns true we got a match and the second template Indexer is used.
    > if const CONT is not a const vector then the first template Indexer is used.
    >
    > you can find the boost library here www.boost.org
    > It is a must . If you don't have it, get it!
    >
    > -------------------------
    >
    > Eric Pruneau


    oh concern to my last post about how to get rid of the extra int ,
    i was stupid enough to forget that CONT::value_type is T,
    so my final version is

    template<typename S,typename enable = void>
    class Indexer;

    template<typename S>
    class Indexer<S,typename boost::enable_if_c<std::tr1::is_same<
    typename std::tr1::add_const<S>::type, const
    std::vector<typename S::value_type,typename
    S::allocator_type>>::value>::type
    > {

    public:
    typedef Indexer<S> self_type;
    typedef Indexer<typename std::tr1::remove_const<S>::type>
    nonconst_self;
    public:
    Indexer(S& s) {
    std::cout<<"vec ctor\n";
    }
    Indexer(nonconst_self& s){
    std::cout<<"vec copy\n";
    }
    };
    template<typename S>
    class Indexer<S,typename boost::enable_if_c<std::tr1::is_same<
    typename boost::add_const<S>::type, const
    std::deque<typename S::value_type,typename
    S::allocator_type>>::value>::type
    > {

    public:
    typedef Indexer<S> self_type;
    typedef Indexer<typename std::tr1::remove_const<S>::type>
    nonconst_self;
    public:
    Indexer(S& s) {
    std::cout<<"deq ctor\n";
    }
    Indexer(nonconst_self& s){
    std::cout<<"deq copy\n";
    }
    };

    and calling syntax is
    typedef std::vector<int> VI;
    VI v;
    Indexer<VI> I1(v);
    Indexer<const VI> I2(v);
    Indexer<const VI> I3(cv);
    //Indexer<int,std::allocator<int>,VI> I4(cv);

    Indexer<QI> I10(q);

    this is what i wanted, and hence the problem is solved.
    Thanks a lot to all.
    abir
     
    abir, Jul 10, 2008
    #6
    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. Chris Theis
    Replies:
    2
    Views:
    500
    Chris Theis
    Jul 24, 2003
  2. tom_usenet
    Replies:
    0
    Views:
    566
    tom_usenet
    Jul 24, 2003
  3. Replies:
    1
    Views:
    2,147
    Gianni Mariani
    Jun 8, 2007
  4. Marc Bissonnette

    Pattern matching : not matching problem

    Marc Bissonnette, Jan 8, 2004, in forum: Perl Misc
    Replies:
    9
    Views:
    260
    Marc Bissonnette
    Jan 13, 2004
  5. Bobby Chamness
    Replies:
    2
    Views:
    262
    Xicheng Jia
    May 3, 2007
Loading...

Share This Page