Jump to content


Check out our Community Blogs

Register and join over 40,000 other developers!


Recent Status Updates

View All Updates

Photo
- - - - -

Inheritance in template-argument

inheritance

  • Please log in to reply
4 replies to this topic

#1 speculatius

speculatius

    CC Addict

  • Advanced Member
  • PipPipPipPipPip
  • 106 posts
  • Location:Slovakia
  • Programming Language:C, Java, C++, PHP, PL/SQL

Posted 22 November 2009 - 02:00 PM

Hello,

I need help with templates. Consider this situation. You have template with one template argument:

template<typename TAttribute>
class TemplateBase {

  TAttribute attr;

public:

  TAttribute getAttr() const {
    return attr;
  }
};

Then you have some classes in inheritance hierarchy:

class ClassA {};

class ClassB: public ClassA {};

First, I need create specialization of TemplateBase for ClassA and give it some new name:

class TemplateA: public TemplateBase<ClassA> {
  //... added some new funcionality
};

Now, I want to specialize this new class more, namely for ClassB. I want to reuse code from TemplateA, but change template argument to ClassB. Something like this:

class TemplateB: public TemplateA<change ClassA to ClassB> {
  //...
};

Logically it is possible, because ClassB is subtype of ClassA => all functionality from TemplateA will be untouched and I can add new functionality.

How can I do this? Or how will you redesign this code to achieve the same effect?
  • 0

#2 WingedPanther73

WingedPanther73

    A spammer's worst nightmare

  • Moderator
  • 17757 posts
  • Location:Upstate, South Carolina
  • Programming Language:C, C++, PL/SQL, Delphi/Object Pascal, Pascal, Transact-SQL, Others
  • Learning:Java, C#, PHP, JavaScript, Lisp, Fortran, Haskell, Others

Posted 23 November 2009 - 08:39 AM

I'm not at all clear on what you're trying to do. TemplateA is NOT a template any more, it's just a class, therefor, your definition of TemplateB doesn't make any sense.
  • 0

Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

My MineCraft server site: http://banishedwings.enjin.com/


#3 speculatius

speculatius

    CC Addict

  • Advanced Member
  • PipPipPipPipPip
  • 106 posts
  • Location:Slovakia
  • Programming Language:C, Java, C++, PHP, PL/SQL

Posted 24 November 2009 - 01:59 AM

TemplateA is NOT a template any more, it's just a class, therefor, your definition of TemplateB doesn't make any sense.


That is exactly my problem. I want TemplateA to be real template. But in addition, I want to declare, that TAttribute must be always of type ClassA (or its subtype). And consequently every template inherited from TemplateA must have TAttribute of type ClassA (or its subtype) as well.

So when I call method getAttr() on whatever object of type TemplateA, it will return at least object of type ClassA.

I think there is something similair in Java, and it looks like <? extends ClassA>
  • 0

#4 ZekeDragon

ZekeDragon

    CC Leader

  • Retired Mod
  • PipPipPipPipPipPipPip
  • 1263 posts

Posted 24 November 2009 - 04:40 AM

I think what it is is that I don't see why it's necessary. You can use ClassB just the same as you can use ClassA, so you don't have to specify to TemplateB that it needs to accept ClassB, it simply does by virtue of it accepting ClassA. Take this code example below, using what you constructed:
class ClassA {};

class ClassB : public ClassA {};

template <typename TAttribute> class TemplateBase
{
    TAttribute attr;
public:
    TemplateBase(TAttribute at)
    {
        attr = at;
    }

    TAttribute getAttr()
    {
        return attr;
    }
};

class TemplateA : public TemplateBase<ClassA>
{
public:
    TemplateA(ClassA a) : TemplateBase<ClassA>(a) {}
};

class TemplateB : public TemplateA
{
public:
    TemplateB(ClassB b) : TemplateA(b) {}
};
You can simply structure your TemplateB to only accept objects of ClassB, then use the code available in it's parent classes, treating each instance of ClassB like it were a ClassA. This makes your new object more specialized, while also not doing anything complex. However, if you're trying to support any object that is of type ClassA (for example, if ClassC inherits from ClassA, and you want to use that in your template as well as a specialization), then C++ does not provide ANY easy answer to this question.

That's right, C++ can't do that.

The closest thing you're going to get to that is Boost.StaticAssert. You should already have Boost if you're doing work with C++, and Static Assert is very useful for checking template arguments. If you don't mind runtime errors instead, you can also go ahead and use dynamic_cast, that's standard.
  • 0
If you enjoy reading this discussion and are thinking about commenting, why not click here to register and start participating in under a minute?

#5 speculatius

speculatius

    CC Addict

  • Advanced Member
  • PipPipPipPipPip
  • 106 posts
  • Location:Slovakia
  • Programming Language:C, Java, C++, PHP, PL/SQL

Posted 25 November 2009 - 03:01 AM

However, if you're trying to support any object that is of type ClassA (for example, if ClassC inherits from ClassA, and you want to use that in your template as well as a specialization), then C++ does not provide ANY easy answer to this question.


Yes, that is what I need :)

I found one solution, which is working for me:

template<TAttribute>
class TeplateA_internal: public TemplateBase<TAttribute> {
  //...
};

typedef TemplateA_internal<ClassA> TemplateA;

template<TAttribute>
class TeplateB_internal: public TemplateA_internal<TAttribute> {
  //...
};

typadef TemplateB_internal<ClassB> TemplateB;

The only disadvantage is, that I have to use static_cast for up-casting:

TemplateA a = [B]static_cast<TemplateA>[/B]( TemplateB(/*...*/) );

But polymorphism works as expected, and that is primarily.

Thank you for all your replies. I will have a look on Boost...
  • 0





Also tagged with one or more of these keywords: inheritance