> Matthew wrote:
>
> >However,
modern template practices have revived the use for MI, in so far as
>
>being able to apply tag inheritance to existing types via bolt-in
templates.
> >D doesn't properly support this at the moment, though I
have no doubt that
> >it will.
> >
> >
>
What is tag inheritance?
template< typename
S
, typename T
= sequence_range_traits<S,
is_const<S>::value>
>
class
sequence_range
: public iterable_range_tag //
<== ** this is the tag **
{
public:
. . .
The tag identifies the range type, which is used in
the range algorithms for selecting the most efficient algorithms.
The tags look like the following:
struct
simple_range_tag
{};
struct
iterable_range_tag
: public
simple_range_tag
{};
struct
noninterruptible_range_tag
{};
[This is an extract from the STLSoft implementation
of the Range concept, which I'm working on with John Torjo. Ranges will also
likely feature large in DTL, although at the moment I've only got so far as
doing the basic list, map, queue, set, stack and vector class implementations,
and exchanging vague ponderings with big-W. As soon as he gets back from SDWest
I expect to see a rapid movement
> What are bolt-in templates?
From [Wils04]:
Definition:
Bolt-ins
Bolt-ins are template classes with the following
characteristics:
1. They derive, usually publicly, from their primary
parameterising type.
2. They accommodate the polymorphic nature of their
primary parameterising type. Usually they also adhere to the nature, but this is
not always the case, and they may define virtual methods of their own, in
addition to overriding those defined by the primary parameterising
type.
3. They may increase the footprint of the primary
parameterising type by the definition of member variables, virtual functions and
additional inheritance from non-empty
types.
>
> Just out of interest could you
give an example?
Classic examples are to be found in ATL, whereby
several separate template classes may provide bolt-in behaviour, i.e.
CComObject<>, CComObjectStack<>, etc.
A (really stupid) simple example (in
C++):
class NumSequence
{
public:
void PresentCalculation(ostream &os, int
maxValue)
{
vector<int>
things(this->CalcThings(maxValue));
copy(things.begin(),
things.end(), ostream_iterator<int>(os));
}
protected:
virtual vector<int>
CalcThings(int maxValue) = 0;
};
template<typename S>
class FibonacciSequence
{
protected:
virtual vector<int>
CalcThings(int maxValue)
{
. . . calculate a Fibonacci sequence up to maxValue, and
return in vector<int>
}
};
template<typename S>
class PrimeSequence
{
protected:
virtual vector<int>
CalcThings(int maxValue)
{
. . . calculate a prime number sequence up to maxValue,
and return in vector<int>
}
};
int main()
{
FibonacciSequence<NumSequence> ps().PresentCalculation(cout);
PrimeSequence<NumSequence>
ps().PresentCalculation(cout);
return 0;
}
I'll leave it to all your great minds to figure out
the amazing real-world benefits of this technique, rather than just my weak
example.
In [Wils04], the sections in the Bolt-ins chapter
are:
22.1 Adding
Functionality
22.2 Skin Selection
22.3 Non-virtual
Overriding
22.4 Leveraging
Scope
22.5 Simulated Compile-time
Polymorphism
22.6 Parameterised Polymorphic
Packaging.
And if you want to know any more than that, you'll
have to buy it (probably available around Sept/Oct). :)