How can we point to itself in template parameter

G

Grizlyk

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
};
 
T

terminator

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
 
T

terminator

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
 
G

Greg

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
 
G

Grizlyk

Greg said:
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());
}
 
G

Grizlyk

Maybe like this:

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

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

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

terminator

Maybe like this:

//make new name with the help of inheritance
template<class Tptr>
class Tc_iterator:
public Viterator<
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.
 
G

Grizlyk

terminator said:
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.
 
T

terminator


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;
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top