Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Mutually referential class templates

Reply
Thread Tools

Mutually referential class templates

 
 
jrwats
Guest
Posts: n/a
 
      01-17-2009
I would like to have a class template A that takes a class B as it's
template parameter and has a static instance ofr it. However that
same B class needs to know class A via templatization. See below

template<class ClassWithStaticFunc>
class CallsStaticFunc {
public:
void CallStaticFunc() {
ClassWithStaticFunc::StaticFunc();
}
};

template<class Caller >
class HasStaticFunc {
public:
static void StaticFunc() {
cout << "This function is static!" << endl;
}
static Caller s_Caller;
};

int main() {
// we can't make an instance that works because trying to
//would need infinitely recursive templates
HasStaticFunc<CallsStaticFunc<HasStaticFunc<Calls. ...> > >
}

Trying to use the "Curiously Recurring template pattern" also does not
work for this problem. I really need HasStaticFunc to have a static
instance of CallsStaticFunc and for CallsStaticFunc to be able to call
any arbitrary HasStaticFunc<CallsStaticFunc>

Note: The below gets done what I need to accomplish, but I REALY want
the StaticClass a template for H. With the below solution, if I add
anymore templates to StaticClass, H would then have to take those in
as parameters as well...

template<class ClassWithStaticFunc>
class CallsStaticFunc {
public:
void CallStaticFunc() {
ClassWithStaticFunc::StaticFunc();
}
};
 
Reply With Quote
 
 
 
 
jrwats
Guest
Posts: n/a
 
      01-17-2009
On Jan 17, 10:23*am, jrwats <(E-Mail Removed)> wrote:
> I would like to have a class template A that takes a class B as it's
> template parameter and has a static instance ofr it. *However that
> same B class needs to know class A via templatization. *See below
>
> template<class ClassWithStaticFunc>
> class CallsStaticFunc {
> public:
> * * void CallStaticFunc() {
> * * * * ClassWithStaticFunc::StaticFunc();
> * * }
>
> };
>
> template<class Caller >
> class HasStaticFunc {
> public:
> * * static void StaticFunc() {
> * * * * cout << "This function is static!" << endl;
> * * }
> * * static Caller s_Caller;
>
> };
>
> int main() {
> * * // we can't make an instance that works because trying to
> * * //would need infinitely recursive templates
> * * HasStaticFunc<CallsStaticFunc<HasStaticFunc<Calls. ...> > >
>
> }
>
> Trying to use the "Curiously Recurring template pattern" also does not
> work for this problem. *I really need HasStaticFunc to have a static
> instance of CallsStaticFunc and for CallsStaticFunc to be able to call
> any arbitrary HasStaticFunc<CallsStaticFunc>
>
> Note: The below gets done what I need to accomplish, but I REALY want
> the StaticClass a template for H. *With the below solution, if I add
> anymore templates to StaticClass, H would then have to take those in
> as parameters as well...
>
> template<class ClassWithStaticFunc>
> class CallsStaticFunc {
> public:
> * * void CallStaticFunc() {
> * * * * ClassWithStaticFunc::StaticFunc();
> * * }
>
> };
>
>


I got it!!!!!!
OMG, this is going to be sexy when I actually use it. I can't
describe how excited I am about this.

The trick was filling the template for the Caller within the Static
class.
The real use behind this is that Stat is a Singleton and I needed a
way to provide access to its static Instance() and Destroy() methods
to a static member it had. Now I can make any type of object to alter
behavior around when Destroy() passed as a template argument to make
custom Singletons that need to be destroyed on certain events!

Anyway, the below compiles (and works as expected):

#include <iostream>

using namespace std;
// Goal: a Class that has a template parameter which it uses as a
// static member variable. That member variable also has access to
// the static methods of the class. That means it needs to know the
// class type.

template <class Static>
class CCaller
{
public:
void run() { cout << "CCaller.run()" << endl; Static::StatFunc
(); }
};

template <class Static>
class CAnotherCaller
{
public:
void run() { cout << "CAnotherCaller.run()" << endl;
Static::StatFunc(); }
};

template <template <class> class Caller>
class CStatic
{
public:
static void StatFunc(){ cout << "Stat<Caller>::StatFunc()" <<
endl; }
static Caller<CStatic <Caller> > s_C;
};

template<template<class> class Caller>
Caller<CStatic<Caller> > CStatic<Caller>::s_C;

int main()
{
CStatic<CCaller> staticC;
CStatic<CAnotherCaller> staticA;
staticC.s_C.run();
staticA.s_C.run();
}
 
Reply With Quote
 
 
 
 
jrwats
Guest
Posts: n/a
 
      01-17-2009
On Jan 17, 12:39*pm, jrwats <(E-Mail Removed)> wrote:
> On Jan 17, 10:23*am, jrwats <(E-Mail Removed)> wrote:


> Now I can make any type of object to alter
> behavior around when Destroy() passed as a template argument to make
> custom Singletons that need to be destroyed on certain events!
>


Above sentence isn't exactly "English"


Now I can make any class (which contains appropriate functions) to
alter behavior (like when to call Destroy() for instance), by passing
a template argument to make custom Singletons that need to be
destroyed on certain events being fired!
 
Reply With Quote
 
jrwats
Guest
Posts: n/a
 
      01-17-2009

> Now I can make any class (which contains appropriate functions) to
> alter behavior (like when to call Destroy() for instance), by passing
> a template argument to make custom Singletons that need to be
> destroyed on certain events being fired!


OK last post. Just to illustrate why my former workaround isn't
nearly as sexy, I can add additional template parameters to the static
class with ease, and the Caller doesn't need to know:


template <class Static>
class CCaller
{
public:
void run()
{
cout << "CCaller.run()" << endl;
Static::StatFunc();
}
};

template <class Static>
class CAnotherCaller
{
public:
void run()
{
cout << "CAnotherCaller.run()" << endl;
Static::StatFunc();
}
};

class SomeClass
{
};

template <template <class> class Caller, class AnotherClass>
class CStatic
{
public:
static void StatFunc()
{
cout << "Stat<Caller>::StatFunc()" << endl;
}
static Caller<CStatic <Caller, AnotherClass> > s_C;
AnotherClass m_AnotherClass;
};

template<template<class> class Caller, class AnotherClass>
Caller<CStatic<Caller, AnotherClass> > CStatic<Caller,
AnotherClass>::s_C;

int main()
{
CStatic<CCaller, SomeClass> staticC;
CStatic<CAnotherCaller, SomeClass> staticA;
staticC.s_C.run();
staticA.s_C.run();
}
 
Reply With Quote
 
Zachary Turner
Guest
Posts: n/a
 
      01-18-2009
On Jan 17, 12:23*pm, jrwats <(E-Mail Removed)> wrote:
> I would like to have a class template A that takes a class B as it's
> template parameter and has a static instance ofr it. *However that
> same B class needs to know class A via templatization. *See below
>
> template<class ClassWithStaticFunc>
> class CallsStaticFunc {
> public:
> * * void CallStaticFunc() {
> * * * * ClassWithStaticFunc::StaticFunc();
> * * }
>
> };
>
> template<class Caller >
> class HasStaticFunc {
> public:
> * * static void StaticFunc() {
> * * * * cout << "This function is static!" << endl;
> * * }
> * * static Caller s_Caller;
>
> };
>
> int main() {
> * * // we can't make an instance that works because trying to
> * * //would need infinitely recursive templates
> * * HasStaticFunc<CallsStaticFunc<HasStaticFunc<Calls. ...> > >
>
> }
>
> Trying to use the "Curiously Recurring template pattern" also does not
> work for this problem. *I really need HasStaticFunc to have a static
> instance of CallsStaticFunc and for CallsStaticFunc to be able to call
> any arbitrary HasStaticFunc<CallsStaticFunc>
>
> Note: The below gets done what I need to accomplish, but I REALY want
> the StaticClass a template for H. *With the below solution, if I add
> anymore templates to StaticClass, H would then have to take those in
> as parameters as well...
>
> template<class ClassWithStaticFunc>
> class CallsStaticFunc {
> public:
> * * void CallStaticFunc() {
> * * * * ClassWithStaticFunc::StaticFunc();
> * * }
>
> };
>
>


It seems extremely odd to me for there to be a legitimate use for such
a technique, but nonetheless I would you refer you to The Fundamental
Law of Computer Science: "Every problem can be solved by adding an
extra level of indirection." In this case you can achieve an extra
level of indirection by using a "template template". You've probably
heard of it, but in case you're not familiar, say you've got a class A
that takes a template argument. You wish to use, as that argument, a
type that is itself a template. This happens all the time in STL, say
you want to declare a vector of lists. You would normally type

vector<list<int> > vec;

But a template template would allow you to omit the "int", and have
the vector be responsible for filling it in with an appropriate type.
Of course vector is already written, but it's just an illustration.
In your case you can apply this as follows:


template<template<class T> class ClassWithStaticFunc>
class CallsStaticFunc {
public:
void CallStaticFunc() {
ClassWithStaticFunc<CallsStaticFunc<ClassWithStati cFunc>
>::StaticFunc();

}

};

template<class Caller>
class HasStaticFunc {
public:
static void StaticFunc() {
cout << "This function is static!" << endl;
}

static Caller s_Caller;

};



int _tmain(int argc, _TCHAR* argv[])
{
CallsStaticFunc<HasStaticFunc> test;
test.CallStaticFunc();

return 0;
}

Let me know if I've misunderstood the problem, but also I fear there
may be some sort of other underlying design problem if this is really
the best solution to your problem (although I've been known to be
wrong)
 
Reply With Quote
 
jrwats
Guest
Posts: n/a
 
      01-18-2009
On Jan 17, 7:19*pm, Zachary Turner <(E-Mail Removed)> wrote:
> On Jan 17, 12:23*pm, jrwats <(E-Mail Removed)> wrote:
>
>
>
> > I would like to have a class template A that takes a class B as it's
> > template parameter and has a static instance ofr it. *However that
> > same B class needs to know class A via templatization. *See below

>
> > template<class ClassWithStaticFunc>
> > class CallsStaticFunc {
> > public:
> > * * void CallStaticFunc() {
> > * * * * ClassWithStaticFunc::StaticFunc();
> > * * }

>
> > };

>
> > template<class Caller >
> > class HasStaticFunc {
> > public:
> > * * static void StaticFunc() {
> > * * * * cout << "This function is static!" << endl;
> > * * }
> > * * static Caller s_Caller;

>
> > };

>
> > int main() {
> > * * // we can't make an instance that works because trying to
> > * * //would need infinitely recursive templates
> > * * HasStaticFunc<CallsStaticFunc<HasStaticFunc<Calls. ...> > >

>
> > }

>
> > Trying to use the "Curiously Recurring template pattern" also does not
> > work for this problem. *I really need HasStaticFunc to have a static
> > instance of CallsStaticFunc and for CallsStaticFunc to be able to call
> > any arbitrary HasStaticFunc<CallsStaticFunc>

>
> > Note: The below gets done what I need to accomplish, but I REALY want
> > the StaticClass a template for H. *With the below solution, if I add
> > anymore templates to StaticClass, H would then have to take those in
> > as parameters as well...

>
> > template<class ClassWithStaticFunc>
> > class CallsStaticFunc {
> > public:
> > * * void CallStaticFunc() {
> > * * * * ClassWithStaticFunc::StaticFunc();
> > * * }

>
> > };

>
> It seems extremely odd to me for there to be a legitimate use for such
> a technique, but nonetheless I would you refer you to The Fundamental
> Law of Computer Science: "Every problem can be solved by adding an
> extra level of indirection." *In this case you can achieve an extra
> level of indirection by using a "template template". *You've probably
> heard of it, but in case you're not familiar, say you've got a class A
> that takes a template argument. *You wish to use, as that argument, a
> type that is itself a template. *This happens all the time in STL, say
> you want to declare a vector of lists. *You would normally type
>
> vector<list<int> > vec;
>
> But a template template would allow you to omit the "int", and have
> the vector be responsible for filling it in with an appropriate type.
> Of course vector is already written, but it's just an illustration.
> In your case you can apply this as follows:
>
> template<template<class T> class ClassWithStaticFunc>
> class CallsStaticFunc {
> public:
> * * void CallStaticFunc() {
> * * * * ClassWithStaticFunc<CallsStaticFunc<ClassWithStati cFunc>>::StaticFunc();
>
> * * }
>
> };
>
> template<class Caller>
> class HasStaticFunc {
> public:
> * * static void StaticFunc() {
> * * * * cout << "This function is static!" << endl;
> * * }
>
> * * static Caller s_Caller;
>
> };
>
> int _tmain(int argc, _TCHAR* argv[])
> {
> * * * * CallsStaticFunc<HasStaticFunc> test;
> * * * * test.CallStaticFunc();
>
> * * * * return 0;
>
> }
>
> Let me know if I've misunderstood the problem, but also I fear there
> may be some sort of other underlying design problem if this is really
> the best solution to your problem (although I've been known to be
> wrong)


Zachary,

Thank you very much for your input! The one difference is I want to
instantiate the HasStaticFunc class rather than the CallsStaticFunc
class. My ultimate goal is to be able to create different types of
HasStaticFunc's by passing in the various different "trait" classes
behaving like CallsStaticFunc.

And I also fear what you mentioned with the underlying design
problem...
The issue is that I need to be able to hook into events (to call
static Instance() and Destroy() methods). Unfortunately our API that
requires an instance of a class (i.e. you can't hook into a static
function) and thus I want to hold a static member that has it's member
functions hooked and can call the static class' Instance() or Destroy
() methods.

I think you used the same "solution" just instead of putting the
"solution" in the HasStaticFun class you put it in the CallsStaticFunc
class. The "solution" being filling adding:
template<template class> class ClassToFillWithArgs
to the template parameter and filling out the parameter from within
the class definition rather when passing the class as an argument.
 
Reply With Quote
 
Zachary Turner
Guest
Posts: n/a
 
      01-18-2009
On Jan 18, 12:44*am, jrwats <(E-Mail Removed)> wrote:
> On Jan 17, 7:19*pm, Zachary *Turner <(E-Mail Removed)> wrote:
>
>
>
> > On Jan 17, 12:23*pm, jrwats <(E-Mail Removed)> wrote:

>
> > > I would like to have a class template A that takes a class B as it's
> > > template parameter and has a static instance ofr it. *However that
> > > same B class needs to know class A via templatization. *See below

>
> > > template<class ClassWithStaticFunc>
> > > class CallsStaticFunc {
> > > public:
> > > * * void CallStaticFunc() {
> > > * * * * ClassWithStaticFunc::StaticFunc();
> > > * * }

>
> > > };

>
> > > template<class Caller >
> > > class HasStaticFunc {
> > > public:
> > > * * static void StaticFunc() {
> > > * * * * cout << "This function is static!" << endl;
> > > * * }
> > > * * static Caller s_Caller;

>
> > > };

>
> > > int main() {
> > > * * // we can't make an instance that works because trying to
> > > * * //would need infinitely recursive templates
> > > * * HasStaticFunc<CallsStaticFunc<HasStaticFunc<Calls. ...> > >

>
> > > }

>
> > > Trying to use the "Curiously Recurring template pattern" also does not
> > > work for this problem. *I really need HasStaticFunc to have a static
> > > instance of CallsStaticFunc and for CallsStaticFunc to be able to call
> > > any arbitrary HasStaticFunc<CallsStaticFunc>

>
> > > Note: The below gets done what I need to accomplish, but I REALY want
> > > the StaticClass a template for H. *With the below solution, if I add
> > > anymore templates to StaticClass, H would then have to take those in
> > > as parameters as well...

>
> > > template<class ClassWithStaticFunc>
> > > class CallsStaticFunc {
> > > public:
> > > * * void CallStaticFunc() {
> > > * * * * ClassWithStaticFunc::StaticFunc();
> > > * * }

>
> > > };

>
> > It seems extremely odd to me for there to be a legitimate use for such
> > a technique, but nonetheless I would you refer you to The Fundamental
> > Law of Computer Science: "Every problem can be solved by adding an
> > extra level of indirection." *In this case you can achieve an extra
> > level of indirection by using a "template template". *You've probably
> > heard of it, but in case you're not familiar, say you've got a class A
> > that takes a template argument. *You wish to use, as that argument, a
> > type that is itself a template. *This happens all the time in STL, say
> > you want to declare a vector of lists. *You would normally type

>
> > vector<list<int> > vec;

>
> > But a template template would allow you to omit the "int", and have
> > the vector be responsible for filling it in with an appropriate type.
> > Of course vector is already written, but it's just an illustration.
> > In your case you can apply this as follows:

>
> > template<template<class T> class ClassWithStaticFunc>
> > class CallsStaticFunc {
> > public:
> > * * void CallStaticFunc() {
> > * * * * ClassWithStaticFunc<CallsStaticFunc<ClassWithStati cFunc>>::StaticFunc();

>
> > * * }

>
> > };

>
> > template<class Caller>
> > class HasStaticFunc {
> > public:
> > * * static void StaticFunc() {
> > * * * * cout << "This function is static!" << endl;
> > * * }

>
> > * * static Caller s_Caller;

>
> > };

>
> > int _tmain(int argc, _TCHAR* argv[])
> > {
> > * * * * CallsStaticFunc<HasStaticFunc> test;
> > * * * * test.CallStaticFunc();

>
> > * * * * return 0;

>
> > }

>
> > Let me know if I've misunderstood the problem, but also I fear there
> > may be some sort of other underlying design problem if this is really
> > the best solution to your problem (although I've been known to be
> > wrong)

>
> Zachary,
>
> Thank you very much for your input! *The one difference is I want to
> instantiate the HasStaticFunc class rather than the CallsStaticFunc
> class. *My ultimate goal is to be able to create different types of
> HasStaticFunc's by passing in the various different "trait" classes
> behaving like CallsStaticFunc.
>
> And I also fear what you mentioned with the underlying design
> problem...
> The issue is that I need to be able to hook into events (to call
> static Instance() and Destroy() methods). *Unfortunately our API that
> requires an instance of a class (i.e. you can't hook into a static
> function) and thus I want to hold a static member that has it's member
> functions hooked and can call the static class' Instance() or Destroy
> () methods.
>
> I think you used the same "solution" just instead of putting the
> "solution" in the HasStaticFun class you put it in the CallsStaticFunc
> class. *The "solution" being filling adding:
> template<template class> class ClassToFillWithArgs
> to the template parameter and filling out the parameter from within
> the class definition rather when passing the class as an argument.


Why does HasStaticFunc need to know anything about the caller? It
would be nice if there was a way to remove this coupling. I guess a
better question is, how would you like the code to look that
ultimately invokes the static function?

Not sure if it's an option but boost has helper classes to encapsulate
arbitrary functions, or things that look / behave like functions into
a common interface.


struct HasStaticFunc
{
static void Func() { cout << "This is a static function!" << endl; }
};

struct HasStaticFunc2
{
static void FuncTwo() { cout << "This is also a static function!" <<
endl; }
};

template<typename Signature>
struct CallsStaticFunc
{
CallsStaticFunc(function<Signature> func)
: _func(func)
{
}

void Call()
{
_func();
}

private:
function<Signature> _func;
};


int main(int argc, char* argv[])
{
CallsStaticFunc<void()> caller1(HasStaticFunc::Func);
CallsStaticFunc<void()> caller2(HasStaticFunc2::FuncTwo);

caller1.Call();
caller2.Call();
return 0;
}

The interesting thing about this technique is that can easily be
extended to static functions with arbitrary signatures by adding
partial specializations of the CallsStatucFunction class. For
example, the following:




struct HasStaticFunc
{
static void Func() { cout << "This is a static function!" << endl; }
};

struct HasStaticFunc2
{
static void FuncTwo() { cout << "This is also a static function!" <<
endl; }
};

struct HasStaticFunc3
{
static double SingleArgFunc(double arg) { return arg + 0.7; }
};


//Fallback class in case no partial specializations match (i.e. the
signature is not supported)
template<typename Signature>
struct CallsStaticFunc
{
};

template<typename R>
struct CallsStaticFunc<R ()>
{
CallsStaticFunc(boost::function<R ()> func)
: _func(func)
{
}

R Call()
{
return _func();
}

private:
boost::function<R()> _func;
};

template<typename R, typename T1>
struct CallsStaticFunc<R (T1)>
{
CallsStaticFunc(boost::function<R (T1)> func)
: _func(func)
{
}

R Call(T1 t1)
{
return _func(t1);
}

private:
boost::function<R (T1)> _func;
};


int main(int argc, char* argv[])
{
CallsStaticFunc<void()> caller1(HasStaticFunc::Func);
CallsStaticFunc<void()> caller2(HasStaticFunc2::FuncTwo);
CallsStaticFunc<double(double)> caller3
(HasStaticFunc3::SingleArgFunc);

caller1.Call();
caller2.Call();
double result = caller3.Call(7.0);
cout << "Returned " << result << endl;
return 0;
}


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
mutually referential (Pg 140 K&R2) G Patel C Programming 14 05-02-2005 07:24 PM
Mutually referential classes Colin JN Breame C++ 5 01-22-2004 08:09 PM
typenames in self-referential templates Anthony Heading C++ 9 09-25-2003 07:21 PM
Re: Mutually referential types Eric C Programming 5 08-17-2003 12:45 AM
Re: Mutually referential types Chris Torek C Programming 1 08-16-2003 04:11 PM



Advertisments