Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Static polymorphism -- what's wrong?

Reply
Thread Tools

Static polymorphism -- what's wrong?

 
 
shablool
Guest
Posts: n/a
 
      10-13-2005
Hi all,
Could someone please explain what is wrong with this code (the compiler
complains about "'int_type' is not a member of 'B'"):


struct B;

template <typename DerivedT>
struct A
{
typedef typename DerivedT::int_type int_type;

int_type get(void) const { return 0; }
};


struct B : public A<B>
{
typedef int int_type;
};

int main()
{
B b;
return b.get();
}

 
Reply With Quote
 
 
 
 
Greg
Guest
Posts: n/a
 
      10-13-2005

shablool wrote:
> Hi all,
> Could someone please explain what is wrong with this code (the compiler
> complains about "'int_type' is not a member of 'B'"):
>
>
> struct B;
>
> template <typename DerivedT>
> struct A
> {
> typedef typename DerivedT::int_type int_type;
>
> int_type get(void) const { return 0; }
> };
>
>
> struct B : public A<B>
> {
> typedef int int_type;
> };
>
> int main()
> {
> B b;
> return b.get();
> }


It seems unlikely that struct A is able to typedef a typedef from one
of its derived classes.

Reversing the typedefs to avoid the circular dependency does fix the
problem:

struct B;

template <typename DerivedT>
struct A
{
typedef int int_type;

int_type get() const { return 0; }
};

struct B : public A<B>
{
using A<B>::int_type;
};

int main()
{
B b;
return b.get();
}

Greg

 
Reply With Quote
 
 
 
 
mlimber
Guest
Posts: n/a
 
      10-13-2005
shablool wrote:
> Hi all,
> Could someone please explain what is wrong with this code (the compiler
> complains about "'int_type' is not a member of 'B'"):
>
>
> struct B;
>
> template <typename DerivedT>
> struct A
> {
> typedef typename DerivedT::int_type int_type;
>
> int_type get(void) const { return 0; }
> };
>
>
> struct B : public A<B>
> {
> typedef int int_type;
> };
>
> int main()
> {
> B b;
> return b.get();
> }


The problem is that B is not defined yet, but you're trying to use it
in A<B>. You can either do what Greg said, or you can break your B
class apart:

struct BAttributes { typedef int int_type; };

template <class T>
struct A
{
typedef typename T::int_type int_type;
int_type get() const { return 0; }
};

struct B : public A<BAttributes>, public BAttributes {};

int main()
{
B b;
return b.get();
}

Note that the multiple inheritance is technically unnecessary here
since A<> duplicates all its types. You would need it only if there
were additional functions, data, or types that A<> did not "copy". BTW,
an easier way to transfer the contents of BAttributes to A<> would be
to treat it like a policy class:

struct BAttributes { typedef int int_type; };

template <class Attributes>
struct A : public Attributes
{
int_type get() const { return 0; }
};

Cheers! --M

 
Reply With Quote
 
Puppet_Sock
Guest
Posts: n/a
 
      10-13-2005
Greg wrote:
[snip context]
> struct B;
>
> template <typename DerivedT>
> struct A
> {
> typedef int int_type;
>
> int_type get() const { return 0; }
> };
>
> struct B : public A<B>
> {
> using A<B>::int_type;
> };
>
> int main()
> {
> B b;
> return b.get();
> }


Ok, that freaks me out. I'd never have thought that you
could derive a class from a template of the same class.
I guess it's because, in this case, A<> only refers to
DerivedT in ways that only need the forward declaration.
If you were to, for example, include a data member in A<>
of type DerivedT, then it would bust. (And the compiler
I use agrees, for what that's worth.)
Socks

 
Reply With Quote
 
mlimber
Guest
Posts: n/a
 
      10-13-2005
Puppet_Sock wrote:
> Greg wrote:
> [snip context]
> > struct B;
> >
> > template <typename DerivedT>
> > struct A
> > {
> > typedef int int_type;
> >
> > int_type get() const { return 0; }
> > };
> >
> > struct B : public A<B>
> > {
> > using A<B>::int_type;
> > };
> >
> > int main()
> > {
> > B b;
> > return b.get();
> > }

>
> Ok, that freaks me out. I'd never have thought that you
> could derive a class from a template of the same class.
> I guess it's because, in this case, A<> only refers to
> DerivedT in ways that only need the forward declaration.
> If you were to, for example, include a data member in A<>
> of type DerivedT, then it would bust. (And the compiler
> I use agrees, for what that's worth.)
> Socks


I use that technique for automatic registration with a factory object.
Assuming Factory<> and Singleton<> classes as found in _Modern C++
Design_'s Loki, I have this in a header file:

// Helper classes for object creation by a factory with a default
// ctor. Concrete classes must implement a static function GetID().
template<class AbstractClass, class ConcreteClass>
class DefaultCreator
{
public:
static std::auto_ptr<AbstractClass> Create()
{
// Verify that the given types are actually super and sub classes
STATIC_CHECK( SUPERSUBCLASS( AbstractClass, ConcreteClass ),
types_are_not_super_and_subclass );

// While the factory will also check at run-time to see if a class
// is registered, we assert on m_registered here to cause a link-
// time failure if we forget to register a concrete command class.
assert( m_registered );

return std::auto_ptr<AbstractClass>( new ConcreteClass );
}
private:
typedef Singleton< Factory<AbstractClass> > theFactory;
static const bool m_registered;
};


// Automatically register all classes that inherit from
// DefaultCreator<>. (Note that these static members appear in header
// file because they are themselves templates. The compiler will
// ensure that there is only one instance of each globally.)

template<class AbstractClass, class ConcreteClass>
const bool DefaultCreator<AbstractClass,ConcreteClass>::m_reg istered =
DefaultCreator<AbstractClass,ConcreteClass>::theFa ctory::Instance()
.Register( ConcreteClass::GetID(), ConcreteClass::Create );


And I use it like so:

class Base {};

class Derived
: public Base
, public DefaultCreator<Base, Derived>
{
public:
static int GetAssignedID() { return 42; }
// ...
};

Then the stuff _Modern C++ Design_ does to register classes with the
factory is automatic for any class inheriting from DefaultCreator<>.

Cheers! --M

 
Reply With Quote
 
mlimber
Guest
Posts: n/a
 
      10-13-2005
mlimber wrote:
> class Derived
> : public Base
> , public DefaultCreator<Base, Derived>
> {
> public:
> static int GetAssignedID() { return 42; }
> // ...
> };

[snip]

Oops. Copy-paste-and-simplify error. That function should be:

static int GetID() { return 42; }

Cheers! --M

 
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
polymorphism in static member functions? --can it be virtual? newbie C++ 6 04-06-2007 10:22 PM
Static Class Variables, Inheritance, and Polymorphism crjjrc C++ 8 04-05-2007 08:39 PM
static polymorphism and Factory Pattern alexander.stippler@uni-ulm.de C++ 8 07-27-2006 10:11 AM
Dynamic polymorphism vs. Static polymorphism Krivenok Dmitry C++ 13 06-01-2006 09:49 AM
Between static & dynamic polymorphism... rwf_20 C++ 15 11-17-2005 09:23 PM



Advertisments