www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - So, how would you use interfaces on this kind of problem?

reply Joey Peters <Joey_member pathlink.com> writes:
First I can tell you I suck at explaining. Anyway, here goes:

Imagine; you're writing a memory modelling class as a base class for other
classes, this class is put in a template, but has it's own public interface per
template instance since it's return types for functions are different per
template. So you start with:

#template Memory(T) {
# class Memory {
#  T[] data;
#  int size() { ... }
#  T[] getData() { return data; }
# }
#}

Then, it's clear you would like to make an interface for it, so that later you
may write different types of memory classes:

#template Memory(T) {
# interface Interface {
#  int size();
#  T[] getData();
# }
# class Memory : Interface {
#  T[] data;
#  int size() { ... }
#  T[] getData() { return data; }
# }
#}

That is a no go for the compiler if you're using the automatic associating
thingy (template NAME(T) class FOO { T ... }). So, what do you do? You name it
differently:

#template Memory(T) {
# interface Interface {
#  int size();
#  T[] getData();
# }
# class Basic : Interface {
#  T[] data;
#  int size() { ... }
#  T[] getData() { return data; }
# }
#}

Imagine you'd now want to use this model on a new type, a stack type (lot's of
imagination here, heh, just trying to make absolute use of interfaces, since
that would be interesting!). But, because this is a stack type, and you want it
to be a container, you want it to be a template too. Besides that, you also want
to be able to write different types of stacks, so you use interfaces so it won't
break compatability with classes that will inherit either one of them stack
types (which then have the interface). So, then, same small problem:

#template Stack(T) {
# class Stack : Memory!(T).Basic { ... }

that is a no go, you'd have to make it Basic again once you want to put in an
interface. How many people are willing to use a STL that would require them to
type this out loud:

Stack!(int).Basic 

And no, you cannot make an alias (maybe you can prove me wrong but I've been
using those for a while), it's a template, and you cannot magically make it
return a type. You 'seem to be able' though, but it seems it doesn't work when
you put interfaces or other things in them. What I want is that

Stack!(int) would be the same as Stack!(int).Basic

I think it's supposed to work. I thought about all kinds of possible ways to fix
this but nothing comes up. It would be so cool if it worked, you could make uber
templates, where you can make everything work to your abidding, make debugger
versions where it keeps track of every operation, etc etc. Though that's more
naziland... Oh right, uber-templates. ;)

Complete examples:

// a memory model
http://svn.dsource.org/svn/projects/dragon-stl/trunk/0.01_0101/memory.d
// the stack model that usees the memory model, yet without interfaces, and
shows lengthy use of template (though it would be less of a problem if it only
happened here)
http://svn.dsource.org/svn/projects/dragon-stl/trunk/0.01_0101/stack.d

I hope someone can prove me wrong.
Sep 12 2004
next sibling parent "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Joey Peters" <Joey_member pathlink.com> wrote in message
news:ci18np$2se3$1 digitaldaemon.com...
 First I can tell you I suck at explaining. Anyway, here goes:

 Imagine; you're writing a memory modelling class as a base class for other
 classes, this class is put in a template, but has it's own public
interface per
 template instance since it's return types for functions are different per
 template. So you start with:

 #template Memory(T) {
 # class Memory {
 #  T[] data;
 #  int size() { ... }
 #  T[] getData() { return data; }
 # }
 #}

 Then, it's clear you would like to make an interface for it, so that later
you
 may write different types of memory classes:

 #template Memory(T) {
 # interface Interface {
 #  int size();
 #  T[] getData();
 # }
 # class Memory : Interface {
 #  T[] data;
 #  int size() { ... }
 #  T[] getData() { return data; }
 # }
 #}

 That is a no go for the compiler if you're using the automatic associating
 thingy (template NAME(T) class FOO { T ... }). So, what do you do? You
name it
 differently:

 #template Memory(T) {
 # interface Interface {
 #  int size();
 #  T[] getData();
 # }
 # class Basic : Interface {
 #  T[] data;
 #  int size() { ... }
 #  T[] getData() { return data; }
 # }
 #}

 Imagine you'd now want to use this model on a new type, a stack type
(lot's of
 imagination here, heh, just trying to make absolute use of interfaces,
since
 that would be interesting!). But, because this is a stack type, and you
want it
 to be a container, you want it to be a template too. Besides that, you
also want
 to be able to write different types of stacks, so you use interfaces so it
won't
 break compatability with classes that will inherit either one of them
stack
 types (which then have the interface). So, then, same small problem:

 #template Stack(T) {
 # class Stack : Memory!(T).Basic { ... }

 that is a no go, you'd have to make it Basic again once you want to put in
an
 interface. How many people are willing to use a STL that would require
them to
 type this out loud:

 Stack!(int).Basic
How about splitting the template into two templates MemoryInterface and MemoryBasic, wouldn't that solve a problem. (although i don't see it as a problem) ;)
 And no, you cannot make an alias (maybe you can prove me wrong but I've
been
 using those for a while), it's a template, and you cannot magically make
it
 return a type. You 'seem to be able' though, but it seems it doesn't work
when
 you put interfaces or other things in them. What I want is that

 Stack!(int) would be the same as Stack!(int).Basic

 I think it's supposed to work. I thought about all kinds of possible ways
to fix
 this but nothing comes up. It would be so cool if it worked, you could
make uber
 templates, where you can make everything work to your abidding, make
debugger
 versions where it keeps track of every operation, etc etc. Though that's
more
 naziland... Oh right, uber-templates. ;)

 Complete examples:

 // a memory model
 http://svn.dsource.org/svn/projects/dragon-stl/trunk/0.01_0101/memory.d
 // the stack model that usees the memory model, yet without interfaces,
and
 shows lengthy use of template (though it would be less of a problem if it
only
 happened here)
 http://svn.dsource.org/svn/projects/dragon-stl/trunk/0.01_0101/stack.d

 I hope someone can prove me wrong.
Sep 12 2004
prev sibling parent reply "Bent Rasmussen" <exo bent-rasmussen.info> writes:
Disambiguate types with names and declare one datatype per template

interface IMemory(T) ...
interface IStack(T) : IMemory!(T) ...
class Memory(T) : IMemory!(T) ...
class Stack(T) : IStack!(T), Memory!(T) ...

Is this sufficient to solve your problem?
Sep 12 2004
parent Joey Peters <Joey_member pathlink.com> writes:
In article <ci1g95$2vdt$1 digitaldaemon.com>, Bent Rasmussen says...
Disambiguate types with names and declare one datatype per template

interface IMemory(T) ...
interface IStack(T) : IMemory!(T) ...
class Memory(T) : IMemory!(T) ...
class Stack(T) : IStack!(T), Memory!(T) ...

Is this sufficient to solve your problem?
That would work, thanks.
Sep 12 2004