Mutually referential class templates

J

jrwats

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();
}
};
 
J

jrwats

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();
}
 
J

jrwats

On Jan 17, 10:23 am, jrwats <[email protected]> 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!
 
J

jrwats

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();
}
 
Z

Zachary Turner

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 said:
::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)
 
J

jrwats

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<ClassWithStaticFunc>>::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.
 
Z

Zachary Turner

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<ClassWithStaticFunc>>::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;
}
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top