'recursive' template problem

A

Alexander Stippler

Hi,

I have a little problem to design some template classes in a realizable way.
I have some Container classes and some Proxy classes (proxies for
elements). Looks like this:

// P is the Proxy class.
template <typename T, typename P>
class Container
{
P
whatever() { return P(); }
};

template <typename T>
class Proxy1 { ... };

template <typename T>
class Proxy2 { ... };

For some reason every instance of class Proxy needs to know, which Container
class it is used for. Some behavior of Proxy is dependend on the specific
Container. So, when I call method whatever() I want to give the information
that I'm inside Container<T, P> to P. But I cannot give the Proxy class the
information via another template parameter, cause I would end up in an
endless recursive definition, since Container is parameterized by the
Proxy. Got my problem?

Best regards,
alex
 
M

Marc

Alexander said:
For some reason every instance of class Proxy needs to know, which Container
class it is used for. Some behavior of Proxy is dependend on the specific
Container. So, when I call method whatever() I want to give the information
that I'm inside Container<T, P> to P. But I cannot give the Proxy class the
information via another template parameter, cause I would end up in an
endless recursive definition, since Container is parameterized by the
Proxy. Got my problem?

What's wrong with:
template <typename T, template <typename> class P>
class Container
{
typedef Container<T,P> Self;
P<Self>
etc
?
Just because you cannot write the type as a single expression does not
mean it is not a valid type.
 
A

Alexander Stippler

Marc said:
What's wrong with:
template <typename T, template <typename> class P>
class Container
{
typedef Container<T,P> Self;
P<Self>
etc
?
Just because you cannot write the type as a single expression does not
mean it is not a valid type.

Thanks. Looks simple and correct. But I guess a default value for P is not
realizable this way, is it?

regards,
alex
 
A

Alexander Stippler

Alexander said:
Thanks. Looks simple and correct. But I guess a default value for P is not
realizable this way, is it?

regards,
alex

I get some doubts. How do I instantiate such a class?

Container<double, Proxy<Container<double, ....
 
V

Victor Bazarov

Alexander said:
Alexander Stippler wrote:




I get some doubts. How do I instantiate such a class?

Container<double, Proxy<Container<double, ....

You probably need some way to terminate the instantiation loop:

Container<double, Proxy<Container<double, NullProxy<void> > > ...

Take a look at TypeList template idiom. The latest CUJ also has
a good article by V.Myrnyy that uses a similar pattern.

Victor
 
A

Alexander Stippler

OK, I will try to formulate my problem more concrete. Perhaps this helps.
Given:

template <typename T>
class Proxy { ... };

template <typename T, typename P = DefaultProxy<T> >
class OneContainerType
{
public:
P
operator()(int pos)
{
return P(int);
}
};

template <typename T, typename P = AnotherDefaultProxy<T> >
class AnotherContainerType
{
...
};

Now I have to pass the information, which Container type called
operator(), since the implementation calls a template function
specialized for each different Container type. But how?
I do not want to provide an additional parameter for the Proxy
constructor (due to efficiency).
Any suggestions?

best regards,
alex
 
V

Victor Bazarov

Alexander Stippler said:
OK, I will try to formulate my problem more concrete. Perhaps this helps.
Given:

template <typename T>
class Proxy { ... };

template <typename T, typename P = DefaultProxy<T> >
class OneContainerType
{
public:
P
operator()(int pos)
{
return P(int);
}
};

template <typename T, typename P = AnotherDefaultProxy<T> >
class AnotherContainerType
{
...

Supposedly the same as in 'OneContainerType', right?
};

Now I have to pass the information, which Container type called
operator(),

You mean, which Container type initialised the P.
since the implementation calls a template function
specialized for each different Container type. But how?
I do not want to provide an additional parameter for the Proxy
constructor (due to efficiency).
Any suggestions?

How about this: you create a templatised 'construct' member function
in your proxy and use that instead of the constructor?

template<class T> class DefaultProxy {
...

DefaultProxy(T t); // normal constructor

template<class C> DefaultProxy construct(T t) {
DefaultProxy dp(t);
// use the 'C' here as you want
...
return dp;
}
};

template <typename T, typename P = DefaultProxy<T> >
class OneContainerType {
P operator()(int pos) {
return P::construct<OneContainerType>(pos);
}
};

(you may need to put the keyword 'template' somewhere here, I am not
sure)

I know, it may not be the solution you seek, but given the information
you provided, I could only come up with this half-assed scheme...

Good luck!

Victor
 
A

Alexander Stippler

Victor said:
How about this: you create a templatised 'construct' member function
in your proxy and use that instead of the constructor?

I will try this. Sounds very good (and too simple not to get it on my
own :-(( ).
Thanks a lot for your help. I was really frustrated already.

Best regards,
Alex
 
A

Alexander Stippler

Hi,

I was exulting to early. My problem wasn't formulated good enough. So your
proposal is adequate for the situation I described, but not for my problem.
Some more details:

Victor said:
You mean, which Container type initialised the P.

Not exactly. Initializing is not enough. The P object has to know
by which Container it was created for all its lifetime. Several member
functions need this information. Thus a templatized constructor is not
enough.
I know, it may not be the solution you seek, but given the information
you provided, I could only come up with this half-assed scheme...

I was really unprecise. Sorry.

Hope you can help me again. This little thing is quite essential for my
application,

Best regards,
alex
 
T

tom_usenet

Hi,

I was exulting to early. My problem wasn't formulated good enough. So your
proposal is adequate for the situation I described, but not for my problem.
Some more details:



Not exactly. Initializing is not enough. The P object has to know
by which Container it was created for all its lifetime. Several member
functions need this information. Thus a templatized constructor is not
enough.


I was really unprecise. Sorry.

Hope you can help me again. This little thing is quite essential for my
application,

How about:

template <typename T, typename Container>
class Proxy
{
public:
Proxy(int pos){}
};

template <typename T, template <class T, class Container> class P>
class OneContainerType
{
public:
typedef P<T, OneContainerType> proxy_type;
proxy_type operator()(int pos)
{
return proxy_type(pos);
}
};

int main()
{
typedef OneContainerType<int, Proxy> container_type;
container_type container;
container_type::proxy_type proxy = container(10);
}

That uses a template template paramenter for the proxy.

Tom
 
A

Alexander Stippler

tom_usenet said:
template <typename T, typename Container>
class Proxy
{
public:
Proxy(int pos){}
};

template <typename T, template <class T, class Container> class P>
class OneContainerType
{
public:
typedef P<T, OneContainerType> proxy_type;
proxy_type operator()(int pos)
{
return proxy_type(pos);
}
};

int main()
{
typedef OneContainerType<int, Proxy> container_type;
container_type container;
container_type::proxy_type proxy = container(10);
}

Interesting approach. If I am honest, I do not understand, why it works, but
the compiler says its fine (as soon as I remove the names from the template
template parameters).
Could you please give me an idea how the typedef works. You just say Proxy,
but how does the compiler know how to instatiate the template parameters of
the Proxy type? Now I know again I know nothing about templates :-<.

Best regards,
alex
 
T

tom_usenet

Interesting approach. If I am honest, I do not understand, why it works, but
the compiler says its fine (as soon as I remove the names from the template
template parameters).

Whoops, the reuse of "T" is the error, but there is no need for the
names, except perhaps for code clarity (as with parameter names in
function prototypes).
Could you please give me an idea how the typedef works. You just say Proxy,
but how does the compiler know how to instatiate the template parameters of
the Proxy type? Now I know again I know nothing about templates :-<.

You can have a template parameter that takes a template.

template <typename T, template <class, class> class P>

That defines the P parameter as taking a template with two type
parameters. Proxy is such a template, so it can be passed in as the P
parameter. Then, inside the definition of OneContainerType, you can
use P as a template with two template type parameters, just like
Proxy:
typedef P<T, OneContainerType> proxy_type;

Then you can instantiate your container types with different proxy
templates, and then use the proxy_type typedef to access the proxy
type that is associated with that container.

Tom
 

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

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top