template<class Child> class Parent with protected constructors

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Grey Plastic

    template<class Child> class Parent with protected constructors

    I have several classes that all keep track of static data. However,
    the manner that they keep track of static data is identical, and so
    I'm using the template<class Child> class Parent { ... }; idiom (don't
    know the name of it, if there is one). The problem is that I don't
    want any of my classes to have public constructors. They should be
    created by a static member function.

    This is what I want to do, save for the fact that this doesn't
    compile:

    template <class Child>
    class Foo {
    protected:
    static Child * foo;
    Foo() { }
    public:
    static Child * get() { if(foo==NULL) return foo=new Child(); return
    foo; }
    };

    class Bar : public Foo<Bar> {
    protected:
    Bar() { }
    };

    class Baz : public Foo<Baz> {
    protected:
    Baz() { }
    };

    Bar * Foo<Bar>::foo = NULL;
    Baz * Foo<Baz>::foo = NULL;

    main() {
    Bar & bar = Bar::get();
    Baz & baz = Baz::get();
    }

    The definition of "get" is flagged as an error, because the
    constructor is protected. I've tried many different things, but
    nothing gives me what I want.

    In my actual code, I'm keeping a static set of all the instances of
    the class, but I produced this simpler snippet for the sake of
    discussion.
  • Leor Zolman

    #2
    Re: template&lt;cla ss Child&gt; class Parent with protected constructors

    On 4 Mar 2004 09:45:19 -0800, greyplastic@hot mail.com (Grey Plastic) wrote:
    [color=blue]
    >I have several classes that all keep track of static data. However,
    >the manner that they keep track of static data is identical, and so
    >I'm using the template<class Child> class Parent { ... }; idiom (don't
    >know the name of it, if there is one). The problem is that I don't
    >want any of my classes to have public constructors. They should be
    >created by a static member function.
    >
    >This is what I want to do, save for the fact that this doesn't
    >compile:
    >
    >template <class Child>
    >class Foo {
    >protected:
    > static Child * foo;
    > Foo() { }
    >public:
    > static Child * get() { if(foo==NULL) return foo=new Child(); return
    >foo; }
    >};
    >
    >class Bar : public Foo<Bar> {
    >protected:
    > Bar() { }
    >};
    >
    >class Baz : public Foo<Baz> {
    >protected:
    > Baz() { }
    >};
    >
    >Bar * Foo<Bar>::foo = NULL;
    >Baz * Foo<Baz>::foo = NULL;
    >
    >main() {
    > Bar & bar = Bar::get();
    > Baz & baz = Baz::get();
    >}
    >
    >The definition of "get" is flagged as an error, because the
    >constructor is protected. I've tried many different things, but
    >nothing gives me what I want.[/color]

    Here's a modified version (comments indicate additions).
    Compiles with: Comeau, MSVC 7,7.1
    NOT: gcc (sigh), Borland, MSVC 6

    #include <iostream> // just for NULL, really
    using namespace std;

    template <class Child>
    class Foo {
    protected:
    static Child * foo;
    Foo() { }
    public:
    static Child * get() {
    if(foo==NULL) return foo=new Child();
    return foo; }
    };

    class Bar : public Foo<Bar> {
    friend class Foo; // added this
    protected:
    Bar() { }
    };

    class Baz : public Foo<Baz> {
    friend class Foo; // added this
    protected:
    Baz() { }
    };

    //template<class Bar>
    template<> // added this
    Bar * Foo<Bar>::foo = NULL;

    //template<class Bar>
    template<> // added this
    Baz * Foo<Baz>::foo = NULL;

    int main() { // returns int
    Bar & bar = *Bar::get(); // added *
    Baz & baz = *Baz::get(); // added *
    return 0; // added this
    }


    HTH,
    -leor
    [color=blue]
    >
    >In my actual code, I'm keeping a static set of all the instances of
    >the class, but I produced this simpler snippet for the sake of
    >discussion.[/color]

    Leor Zolman
    BD Software
    leor@bdsoft.com
    www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
    C++ users: Download BD Software's free STL Error Message
    Decryptor at www.bdsoft.com/tools/stlfilt.html

    Comment

    • Gianni Mariani

      #3
      Re: template&lt;cla ss Child&gt; class Parent with protected constructors

      Leor Zolman wrote:[color=blue]
      > On 4 Mar 2004 09:45:19 -0800, greyplastic@hot mail.com (Grey Plastic) wrote:
      >[/color]
      ....[color=blue]
      >
      >
      > Here's a modified version (comments indicate additions).
      > Compiles with: Comeau, MSVC 7,7.1
      > NOT: gcc (sigh), Borland, MSVC 6
      >
      > #include <iostream> // just for NULL, really
      > using namespace std;
      >
      > template <class Child>
      > class Foo {
      > protected:
      > static Child * foo;
      > Foo() { }
      > public:
      > static Child * get() {
      > if(foo==NULL) return foo=new Child();
      > return foo; }
      > };
      >
      > class Bar : public Foo<Bar> {
      > friend class Foo; // added this[/color]

      I don't believe that this is valid C++ code anyway. There is no
      class Foo as it is not a template.

      This might be more correct:

      friend class Foo<bar>;

      If you want all Foo's to access Bar you can do this:

      template <class Child> friend class Foo;

      [color=blue]
      > protected:
      > Bar() { }
      > };
      >
      > class Baz : public Foo<Baz> {
      > friend class Foo; // added this[/color]

      .... ditto ...
      [color=blue]
      > protected:
      > Baz() { }
      > };
      >
      > //template<class Bar>
      > template<> // added this
      > Bar * Foo<Bar>::foo = NULL;[/color]

      Bar * Foo<Bar>::foo = 0; // :-)

      I remember a discussion on this group a while back about using NULL. I
      think the conclusion was that NULL was worse than useless and that the
      literal 0 was much easier to deal with. It was along the lines of
      confusion with the C version (or historic) NULL which was (void *)0 and
      the fact the C++ has different semantics with void *.
      [color=blue]
      >
      > //template<class Bar>
      > template<> // added this
      > Baz * Foo<Baz>::foo = NULL;
      >
      > int main() { // returns int
      > Bar & bar = *Bar::get(); // added *
      > Baz & baz = *Baz::get(); // added *
      > return 0; // added this
      > }
      >[/color]

      g

      Comment

      • Leor Zolman

        #4
        Re: template&lt;cla ss Child&gt; class Parent with protected constructors

        On 04 Mar 2004 14:46:57 EST, Gianni Mariani <gi2nospam@mari ani.ws> wrote:

        [color=blue][color=green]
        >> class Bar : public Foo<Bar> {
        >> friend class Foo; // added this[/color]
        >
        >I don't believe that this is valid C++ code anyway. There is no
        >class Foo as it is not a template.
        >
        >This might be more correct:
        >
        > friend class Foo<bar>;
        >[/color]

        Your version has the advantage of compiling with just about everything
        under the sun (even MSVC6, gasp). I'm not yet convinced mine was illegal,
        though...

        [color=blue][color=green]
        >> //template<class Bar>
        >> template<> // added this
        >> Bar * Foo<Bar>::foo = NULL;[/color]
        >
        >Bar * Foo<Bar>::foo = 0; // :-)
        >
        >I remember a discussion on this group a while back about using NULL. I
        >think the conclusion was that NULL was worse than useless and that the
        >literal 0 was much easier to deal with. It was along the lines of
        >confusion with the C version (or historic) NULL which was (void *)0 and
        >the fact the C++ has different semantics with void *.
        >[/color]

        No doubt; in fact, I ended up changing them all to 0 after I posted so that
        I could un-#include the header file in order to get it to compile in strict
        mode under certain platforms. I try to post modified code with the fewest
        possible changes from the OP's code, though, that aren't critical to the
        issue at hand...just to avoid confusion. Not sure it always has that
        effect...
        -leor

        Leor Zolman
        BD Software
        leor@bdsoft.com
        www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
        C++ users: Download BD Software's free STL Error Message
        Decryptor at www.bdsoft.com/tools/stlfilt.html

        Comment

        • pw4getter

          #5
          Re: template&lt;cla ss Child&gt; class Parent with protected constructors

          greyplastic@hot mail.com (Grey Plastic) wrote in message news:<1de04d38. 0403040945.6727 fe08@posting.go ogle.com>...[color=blue]
          > I have several classes that all keep track of static data. However,
          > the manner that they keep track of static data is identical, and so
          > I'm using the template<class Child> class Parent { ... }; idiom (don't
          > know the name of it, if there is one). The problem is that I don't
          > want any of my classes to have public constructors. They should be
          > created by a static member function.
          >
          > This is what I want to do, save for the fact that this doesn't
          > compile:
          >
          > template <class Child>
          > class Foo {
          > protected:
          > static Child * foo;
          > Foo() { }
          > public:
          > static Child * get() { if(foo==NULL) return foo=new Child(); return
          > foo; }
          > };
          >
          > class Bar : public Foo<Bar> {
          > protected:
          > Bar() { }
          > };
          >
          > class Baz : public Foo<Baz> {
          > protected:
          > Baz() { }
          > };
          >
          > Bar * Foo<Bar>::foo = NULL;
          > Baz * Foo<Baz>::foo = NULL;
          >
          > main() {
          > Bar & bar = Bar::get();
          > Baz & baz = Baz::get();
          > }
          >
          > The definition of "get" is flagged as an error, because the
          > constructor is protected. I've tried many different things, but
          > nothing gives me what I want.
          >
          > In my actual code, I'm keeping a static set of all the instances of
          > the class, but I produced this simpler snippet for the sake of
          > discussion.[/color]

          That idiom called "Singleton" . The remaining posts actually answered
          all the questions, so I'm off..

          Comment

          Working...