www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Overriding Template Methods

reply Daniel L. Alves <daniel_lopes_alves hotmail.com> writes:
Hi,
I don't know if this is a bug or if I'm doing something wrong, but I'm not
being able to override template methods. This can be seen with this simple code:

class Base
{
    void writeValueType( T )( T value )
    {
        writefln( "This is Base.writeValueType: value %s has type %s", value,
typeid( value ) );
    }
}

class Derived : Base
{
    override void writeValueType( T )( T value )
    {
        writefln( "This is Derived.writeValueType: value %s has type %s",
value, typeid( value ) );
    }
}

void main()
{
    Base b = new Derived();
    b.writeValueType( true );
}

The output should be:

This is Derived.writeValueType: value true has type bool

But, instead, it is:

This is Base.writeValueType: value true has type bool

Am I missing something?
Jan 29 2012
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 01/29/2012 06:23 PM, Daniel L. Alves wrote:
 Hi,
 I don't know if this is a bug or if I'm doing something wrong, but 
I'm not
 being able to override template methods. This can be seen with this 
simple code:
 class Base
 {
      void writeValueType( T )( T value )
      {
          writefln( "This is Base.writeValueType: value %s has type 
%s", value,
 typeid( value ) );
      }
 }

 class Derived : Base
 {
      override void writeValueType( T )( T value )
      {
          writefln( "This is Derived.writeValueType: value %s has type 
%s",
 value, typeid( value ) );
      }
 }

 void main()
 {
      Base b = new Derived();
      b.writeValueType( true );
 }

 The output should be:

 This is Derived.writeValueType: value true has type bool

 But, instead, it is:

 This is Base.writeValueType: value true has type bool

 Am I missing something?
Template member functions cannot be virtual. One quick reason why this is so is that Derived.writeValueType would have to be instantiated by the compiler, for every possible type in the program. This would lead to almost infinitely large virtual function pointer table. I don't know whether the compiler could refuse the code to compile with that 'override' keyword, but luckily the code is rejected as soon as you add the following two lines: Derived d = new Derived(); d.writeValueType(true); Only then the compiler sees the problem: Error: function deneme.Derived.writeValueType!(bool).writeValueType cannot override a non-virtual function And that kind of makes sense, because the templates are compiled only if they are used and only for the types that they are used with. Ali
Jan 29 2012
next sibling parent Daniel L. Alves <daniel_lopes_alves hotmail.com> writes:
Hey,
thank you very much for the explanation!

Daniel
Jan 29 2012
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Jan 29, 2012 at 06:43:39PM -0800, Ali Çehreli wrote:
[...]
 Template member functions cannot be virtual.
 
 One quick reason why this is so is that Derived.writeValueType would
 have to be instantiated by the compiler, for every possible type in
 the program. This would lead to almost infinitely large virtual
 function pointer table.
[...] I wonder, though, if there are ways of simulating overridable template members by clever use of opDispatch(). Having said that, if you ever get to the point where you can't get around needing overridable template members, then it may be a sign that you're trying to represent simulated types by language types and simulated objects by language objects, whereas the two are different beasts. The solution is to work at a higher level of abstraction. This kind of thing happens, for example, when you're trying to do, say, a physics simulation where you have various types of particles that interact with each other. It may be possible up to a point to represent each type of particle as a separate class, perhaps with a class hierarchy of some sort. But there comes a point where you need to treat simulated types (i.e., particle types) as distinct from the programming language's types. I.e., you have a Particle class that stores an enum that represents what type the particle is (not to be confused with the programming language's types), and perhaps an array of attributes associated with the particle (as opposed to coding each attribute into a distinct field). Particle interactions then are handled by a single method that takes a string or enum type representing what kind of interaction it is, rather than mapping each interaction to a method. This kind of implementation is necessary if, say, the particles have runtime-variable attribute lists, or runtime-variable types, or even types that emerge at runtime. Or when simulated particles don't really behave like programming language class objects, and therefore don't map very well onto the OO paradigm. T -- Do not reason with the unreasonable; you lose by definition.
Jan 29 2012