Mutually referential class templates

Discussion in 'C++' started by jrwats, Jan 17, 2009.

  1. jrwats

    jrwats Guest

    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();
    }
    };
    jrwats, Jan 17, 2009
    #1
    1. Advertising

  2. jrwats

    jrwats Guest

    On Jan 17, 10:23 am, jrwats <> 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();
    }
    jrwats, Jan 17, 2009
    #2
    1. Advertising

  3. jrwats

    jrwats Guest

    On Jan 17, 12:39 pm, jrwats <> wrote:
    > On Jan 17, 10:23 am, jrwats <> 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!
    jrwats, Jan 17, 2009
    #3
  4. jrwats

    jrwats Guest


    > 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();
    }
    jrwats, Jan 17, 2009
    #4
  5. On Jan 17, 12:23 pm, jrwats <> 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<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 Turner, Jan 18, 2009
    #5
  6. jrwats

    jrwats Guest

    On Jan 17, 7:19 pm, Zachary Turner <> wrote:
    > On Jan 17, 12:23 pm, jrwats <> 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<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.
    jrwats, Jan 18, 2009
    #6
  7. On Jan 18, 12:44 am, jrwats <> wrote:
    > On Jan 17, 7:19 pm, Zachary  Turner <> wrote:
    >
    >
    >
    > > On Jan 17, 12:23 pm, jrwats <> 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<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;
    }
    Zachary Turner, Jan 18, 2009
    #7
    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. Anthony Heading

    typenames in self-referential templates

    Anthony Heading, Sep 24, 2003, in forum: C++
    Replies:
    9
    Views:
    454
    Shane Beasley
    Sep 25, 2003
  2. Colin JN Breame

    Mutually referential classes

    Colin JN Breame, Jan 21, 2004, in forum: C++
    Replies:
    5
    Views:
    395
    Colin JN Breame
    Jan 22, 2004
  3. Eric

    Re: Mutually referential types

    Eric, Aug 15, 2003, in forum: C Programming
    Replies:
    5
    Views:
    344
    Mark Haigh
    Aug 17, 2003
  4. Chris Torek

    Re: Mutually referential types

    Chris Torek, Aug 15, 2003, in forum: C Programming
    Replies:
    1
    Views:
    295
    Colin JN Breame
    Aug 16, 2003
  5. G Patel

    mutually referential (Pg 140 K&R2)

    G Patel, Apr 23, 2005, in forum: C Programming
    Replies:
    14
    Views:
    652
Loading...

Share This Page