How can we point to itself in template parameter

Discussion in 'C++' started by Grizlyk, Jan 28, 2007.

  1. Grizlyk

    Grizlyk Guest

    Grizlyk wrote:

    I need to point self class in template parameter, for example

    template <
    class Tptr,
    class Tc_iterator
    >

    class Vcontainer
    {
    public:
    virtual void add_befor(Tc_iterator&, const Tptr);

    virtual ~Vcontainer(){}
    };

    template <
    class Tptr,
    class Tc_container
    >

    class Viterator
    {
    public:
    virtual char next(const char is_check_bound=0);

    Tc_container *container;

    virtual ~Viterator(){}
    };

    class Tptr;
    Viterator< Tptr, Vcontainer<Tptr,"Viterator"> > a;

    How can we point to itself here: "Viterator" (after class "Viterator" has
    been declared)?

    We need only name of class in the case. It can be easy done for non-template
    class

    class X
    {
    public:
    X* next; //I can do it
    };


    --
    Maksim A Polyanin
     
    Grizlyk, Jan 28, 2007
    #1
    1. Advertising

  2. Grizlyk

    terminator Guest

    On Jan 28, 2:52 pm, "Grizlyk" <> wrote:
    > Grizlyk wrote:I need to point self class in template parameter, for example
    >
    > template <
    > class Tptr,
    > class Tc_iterator
    > >

    > class Vcontainer
    > {
    > public:
    > virtual void add_befor(Tc_iterator&, const Tptr);
    >
    > virtual ~Vcontainer(){}
    >
    > };template <
    > class Tptr,
    > class Tc_container
    > >

    > class Viterator
    > {
    > public:
    > virtual char next(const char is_check_bound=0);
    >
    > Tc_container *container;
    >
    > virtual ~Viterator(){}
    >
    > };class Tptr;
    > Viterator< Tptr, Vcontainer<Tptr,"Viterator"> > a;
    >
    > How can we point to itself here: "Viterator" (after class "Viterator" has
    > been declared)?
    >
    > We need only name of class in the case. It can be easy done for non-template
    > class
    >
    > class X
    > {
    > public:
    > X* next; //I can do it
    >
    > };--
    > Maksim A Polyanin


    A template is not a typename unless its arguments are evaluated
    first .So you can not recurse when sending parameters to a
    template.BUT I just successfully tested the following nestrick
    (nesting trick) on VC7.I wanted to pass the "generic" template to
    itself as an argument:

    template <typename ty>
    struct generic{
    typedef typename ty::TResult * TPointer;
    TPointer ptr;
    };

    template<typename ty>
    struct type{//for every other type
    typedef ty TResult;
    };

    struct generic_self{//for generic itself only
    typedef generic<generic_self> TResult;
    };

    generic< type<int> > Gi; //a generic for int
    generic< generic_self > GG; //a generic for generic
     
    terminator, Jan 28, 2007
    #2
    1. Advertising

  3. Grizlyk

    terminator Guest

    On Jan 28, 2:52 pm, "Grizlyk" <> wrote:
    > Grizlyk wrote:I need to point self class in template parameter, for example
    >
    > template <
    > class Tptr,
    > class Tc_iterator
    > >

    > class Vcontainer
    > {
    > public:
    > virtual void add_befor(Tc_iterator&, const Tptr);
    >
    > virtual ~Vcontainer(){}
    >
    > };template <
    > class Tptr,
    > class Tc_container
    > >

    > class Viterator
    > {
    > public:
    > virtual char next(const char is_check_bound=0);
    >
    > Tc_container *container;
    >
    > virtual ~Viterator(){}
    >
    > };class Tptr;
    > Viterator< Tptr, Vcontainer<Tptr,"Viterator"> > a;
    >
    > How can we point to itself here: "Viterator" (after class "Viterator" has
    > been declared)?
    >
    > We need only name of class in the case. It can be easy done for non-template
    > class
    >
    > class X
    > {
    > public:
    > X* next; //I can do it
    >
    > };--
    > Maksim A Polyanin


    A template is not a typename unless its arguments are evaluated
    first .So you can not recurse when sending parameters to a
    template.BUT I just successfully tested the following nestrick
    (nesting trick) on VC7.I wanted to pass the "generic" template to
    itself as an argument:

    template <typename ty>
    struct generic{
    typedef typename ty::TResult * TPointer;
    TPointer ptr;
    };

    template<typename ty>
    struct type{//for every other type
    typedef ty TResult;
    };

    struct generic_self{//for generic itself only
    typedef generic<generic_self> TResult;
    };

    generic< type<int> > Gi; //a generic for int
    generic< generic_self > GG; //a generic for generic
     
    terminator, Jan 28, 2007
    #3
  4. Grizlyk

    Greg Guest

    On Jan 28, 3:52 am, "Grizlyk" <> wrote:
    > Grizlyk wrote:I need to point self class in template parameter, for example
    > template <
    > class Tptr,
    > class Tc_container
    > >

    > class Viterator
    > {
    > public:
    > virtual char next(const char is_check_bound=0);
    >
    > Tc_container *container;
    >
    > virtual ~Viterator(){}
    >
    > };
    >
    > class Tptr;
    > Viterator< Tptr, Vcontainer<Tptr,"Viterator"> > a;
    >
    > How can we point to itself here: "Viterator" (after class "Viterator" has
    > been declared)?


    There is no class named Viterator - only a class template named
    Viterator. And a class template is not a class - nor even a type.

    Now it is possible to create classes from the Viterator class
    template. Classes created in this way are named VIterator<Type1,
    Type2> where Type1 and Type2 are the names of the parameterized types
    used to instantiate the Viterator class template.

    > We need only name of class in the case. It can be easy done for non-template
    > class
    >
    > class X
    > {
    > public:
    > X* next; //I can do it
    >
    > };--


    Viterator can do the same:

    template <class T1, class T2>
    class Viterator
    {
    public:
    Viterator * next;
    ...
    };

    But the actual request in this case is entirely different.
    Essentially, the aim is to instantiate the class template,
    Viterator,with two types: T1 and T2, and have T2 be the type:
    Viterator<T1, T2>. In other words T2 in Viterator<T1, T2> is supposed
    to be none other than Viterator<T1, T2> itself.

    Well, it would be a neat trick if it could be pulled off, but sadly,
    it's not possible in C++ to instantiate a class template with the
    complete, instantiated type as one of its own type parameters. In
    other words, in order to instantaite Viterator in this case, the
    program must first instantiate Viterator, but before that can be done,
    the program must first instantiate Viterator - and so on and so forth.
    So even if this kind of self-referential instantiation were allowed in
    C++ - the infinite recursion involved would translate into a long wait
    for the program to finish compiling.

    Greg
     
    Greg, Jan 28, 2007
    #4
  5. Grizlyk

    Grizlyk Guest

    Greg wrote:
    >
    > So even if this kind of self-referential instantiation were allowed in
    > C++ - the infinite recursion involved would translate into a long wait
    > for the program to finish compiling.



    Not of course, no recursion here. In my example class template parameter
    refering to self class, so compiler can delay generating concrete class till
    all class declaration will be read (to point "};").

    C++ must allow to do something like this
    typedef Viterator< Tptr, Vcontainer<Tptr,Viterator > > Tc_iterator;

    Using a template name without template parameters is allowed in other
    places, for example
    virtual ~Viterator(){} // not Viterator< T1, T2 >

    We can do something like this manualy (it can be compiled)

    template <
    class Tptr,
    class Tc_iterator
    >

    class Vcontainer
    {
    public:
    virtual void add_befor(Tc_iterator&, const Tptr);

    virtual ~Vcontainer(){}
    };

    template <
    class Tptr,
    class Tc_container
    >

    class Viterator
    {
    public:
    virtual char next(const char is_check_bound=0);

    Tc_container *container;

    virtual ~Viterator(){}
    };

    class Tptr;

    //typedef Viterator< Tptr, Vcontainer<Tptr,Viterator> > Tc_iterator;
    class Tc_iterator;

    Viterator< Tptr, Vcontainer<Tptr,Tc_iterator> > a;

    //at the point inheritance do nothing except introducing new name
    class Tc_iterator: public Viterator< Tptr, Vcontainer<Tptr,Tc_iterator> >
    {
    };

    class Tptr{};
    typedef Viterator< Tptr, Vcontainer<Tptr,Viterator> > Tc_iterator2;

    Vcontainer < Tptr, Tc_iterator2 > b;

    void foo()
    {
    a.container=0;
    b.add_befor(a,Tptr());
    }

    --
    Maksim A Polyanin
     
    Grizlyk, Jan 28, 2007
    #5
  6. Grizlyk

    Grizlyk Guest

    > class Tptr{};
    > typedef Viterator< Tptr, Vcontainer<Tptr,Viterator> > Tc_iterator2;
    >


    No, error
    typedef Viterator< Tptr, Vcontainer<Tptr,Tc_iterator> > Tc_iterator2;

    > Vcontainer < Tptr, Tc_iterator2 > b;
    >
    > void foo()
    > {
    > a.container=0;
    > b.add_befor(a,Tptr());
    > }
    >


    --
    Maksim A Polyanin
     
    Grizlyk, Jan 28, 2007
    #6
  7. Grizlyk

    Grizlyk Guest

    Maybe like this:

    //make new name with the help of inheritance
    template<class Tptr>
    class Tc_iterator:
    public Viterator<
    Tptr,
    Vcontainer<Tptr,Tc_iterator<Tptr> >
    >

    {
    };

    class Tptr{};
    Tc_iterator<Tptr> a;
    Vcontainer < Tptr, Tc_iterator<Tptr> > b;

    int main()
    {
    a.container=&b;
    b.add_befor(a,Tptr());
    }

    --
    Maksim A Polyanin
     
    Grizlyk, Jan 28, 2007
    #7
  8. Grizlyk

    terminator Guest

    On Jan 28, 6:52 pm, "Grizlyk" <> wrote:
    > Maybe like this:
    >
    > //make new name with the help of inheritance
    > template<class Tptr>
    > class Tc_iterator:
    > public Viterator<
    > Tptr,
    > Vcontainer<Tptr,Tc_iterator<Tptr> >
    > >

    > {
    >
    > };class Tptr{};
    > Tc_iterator<Tptr> a;
    > Vcontainer < Tptr, Tc_iterator<Tptr> > b;
    >
    > int main()
    > {
    > a.container=&b;
    > b.add_befor(a,Tptr());
    >
    > }--
    > Maksim A Polyanin


    You lose a lot in this way the constructors are not usable after
    inheritance and actualy you are using a different type which might
    cause pointer casting problems later.If you think that you might need
    to pass the the type as the argument to itself its better to device
    the trick I mentioned in my previous post.Moreover most of the time
    such programs behave like worms because of program rational defects ;
    this case is different from self pointing classes you pointed in your
    previous post.

    >We need only name of class in the case. It can be easy done for non-template
    >class


    >class X
    >{
    >public:
    > X* next; //I can do it
    >};
     
    terminator, Jan 28, 2007
    #8
  9. Grizlyk

    Grizlyk Guest

    terminator wrote:
    >
    > If you think that you might need
    > to pass the the type as the argument to itself its better to device
    > the trick I mentioned in my previous post.


    Yes.

    --
    Maksim A Polyanin
     
    Grizlyk, Jan 28, 2007
    #9
  10. Grizlyk

    terminator Guest

    On Jan 28, 8:26 pm, "Grizlyk" <> wrote:
    > terminator wrote:
    >
    > > If you think that you might need
    > > to pass the the type as the argument to itself its better to device
    > > the trick I mentioned in my previous post.

    >Yes.
    >
    > --
    > Maksim A Polyanin


    check this too:


    template <typename traits>
    struct generic2 {
    typedef typename traits::first first;
    typedef typename traits::second second;
    first * ptr1;
    second * ptr2;
    };

    template <typename A,typename B>
    struct for_2_types{
    typedef A first;
    typedef B second;
    };

    template <typename B>
    struct generic_self_1{
    typedef generic2<generic_self_1> first;
    typedef B second;
    };

    template <typename A>
    struct generic_self_2{
    typedef A first;
    typedef generic2<generic_self_2> second;
    };


    struct generic_self_both{
    typedef generic2<generic_self_both> first,second;
    };

    // generic2 for int,double
    generic2<for_2_types<int,double> > G_id;

    // generic2 for generic2,float
    generic2<generic_self_1<float> > G_Gf;

    // generic2 for char,generic2
    generic2<generic_self_2<char> > G_cG;

    // generic2 for generic2,generic2
    generic2<generic_self_both > G_GG;
     
    terminator, Jan 29, 2007
    #10
    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. Gianni Mariani
    Replies:
    1
    Views:
    353
    tom_usenet
    Sep 5, 2003
  2. mark4asp
    Replies:
    2
    Views:
    2,222
    Harry Haller
    Nov 7, 2006
  3. Stuart Redmann
    Replies:
    5
    Views:
    482
    Stuart Redmann
    Dec 14, 2007
  4. KevinSimonson
    Replies:
    9
    Views:
    607
    Jeff Higgins
    Oct 11, 2011
  5. Saraswati lakki
    Replies:
    0
    Views:
    1,350
    Saraswati lakki
    Jan 6, 2012
Loading...

Share This Page