Click here to Skip to main content
Click here to Skip to main content

Fun With Templates: Part 1

By , 11 Jun 2003
 

Introduction

Like many of the features of C++, template classes are mostly used for the immediate task that they were designed for, giving programmers the ability to create re-usable classes which are abstracted from the type that they are designed to work on. It is a little known fact that templates can be applied to almost any token that appears in the class definition, which opens up some interesting possibilities.

This is also my first foray into the world of Code Project article writing, so any feedback would be most appreciated. No example code has been supplied, the reason for this being that the focus of this article is the design principles more than a specific piece of code.

Using templates to specify parent classes

Did you know you can use templates to specify what class your template class inherits from?

Consider the following piece of code:

template <class Parent> 
class MyClass : public Parent
{
public:
    void Foo();
};

Simple. By specifying Parent as a template parameter, you can now instantiate the class by specifying the parent class in the declaration as follows:

MyClass<CWnd> m_MyWndDerivedClass

m_MyWndDerivedClass is now an instantiation of MyClass, which in turn derives its behavior from CWnd. By changing the template parameter you can change what class MyClass inherits from on the fly. This means any behavior defined in MyClass can be applied to any class it inherits from. Kind of polymorphism in reverse, albeit not as powerful. Of course it is important to make sure that your class has member functions and variables that will not conflict with and foreseeable parent classes, so it would be a good idea to add an additional identifier to all variable/function names--such as MyClass_Init()

So what use is this? The possibilities are endless. But there is one especially good reason why this functionality is of great use, and that is when you begin to explore policy classes.

Policy Class Systems

Policy Class Systems are built upon the principal that, instead of defining concrete classes which have a predetermined set of behaviors, you actually design smaller "task related" classes named "Policies". Whenever there are multiple methods of performing a task, a policy class could be used to reflect the behavior. A compound class can then be constructed by the end-user of your library using any combination of the available policies. For example, a compound class could be composed of three main policies: A "Creation Policy", which handles how the object is created, where it is created, how memory was allocated, and so on and so forth; an "Initialization Policy", which could specify how the class is prepared for use, whether all the values are set to 0, whether the class should read data from a file, and so forth; the final policy could be a "Functionality Policy", which may specify whether the class should add a record to a database, send an e-mail to someone, or whatever. Truth be told, a policy based class would never have such a generalized policy as "what it actually does", but it will serve well as an example.

So how does one go about creating policies?

First off you need to decide what policies are relevant to the class. In the above example, I described three policies: "Creation", "Initialization" and "Functionality". A policy is declared as a standard templated class as follows:

template <class T> 
class CreationNew    
{
public:
    static T* Create()
    {
        return new T;
    }
};

By writing this class, we have enforced a common interface that must be shared between all creation policies, which is that they must all contain a Create method, taking no parameters and returning a pointer to a T object. You can derive from an abstract interface if you wish to further enforce this interface.

This is one of the possible creation policies used by our system. CreationNew is the most basic creation method, and simply allocates memory using the new operator, and returns a pointer. Here is another:

template <class T> 
class CreationPrototype {
public:
    static T* Create() { 

return new T(_item); };

protected:
    static T *_item;
};

This creation policy uses a prototype which is cloned whenever a new object of type T is requested.

The same method applies for creating the initialization policies, though their interface will differ in that they all contain a member function named Init as follows:

template <class T> class InitialisationZero 
                    { public: static void Init(T *pObj) { 
memset(pObj, 0, sizeof(T)); };
};

And finally the functionality policies, but as I said earlier having such a generalized policy for the functionality of your class isn't a good idea. After all you designed the class for a specific reason. Policy classes should relate to different methods of completing the same task, not different tasks altogether.

class FunctionalityHelloWorld { public: void DoSomething() { 
cout << "Hello World!"; };
};

Again, the common interface here is the DoSomething function, which should be present in all "Functionality Policies".

So now that we have designed all our policies, how do we create the compound class that will exploit them?

template 
<
    class CreationPolicy,
    class InitPolicy,
    class FunctionalityPolicy
> 
class CompoundClass : public CreationPolicy, 
   public InitPolicy, public FunctionalityPolicy 
{ 
};

There, simple, now the end-user can construct the compound class from the various policies, by using typedefs as follows:

typedef CompoundClass< CreationNew<MyClass>, 
   InitialisationZero<MyClass>, 
   FunctionalityHelloWorld > MyCompoundClass;
typedef CompoundClass< CreationPrototype<MyClass>, 
  InitialisationZero<MyClass>, 
  FunctionalitySendMail > MyOtherCompoundClass;

MyCompoundClass will now have three functions: Create, Init, and DoSomething, each of which is tailored to exactly how the user wants them to behave. By specifying MyClass in the template parameters, we can also specify what class the compound class works with. This is extremely useful for creating object factories and the like, especially when typelists are used (more about that another time).

But supposing you already know what class the CompoundClass is to work with? In that case, having to explicitly specify the class in a template parameter is just more clutter to the end-user. This is where "template template parameters" come in. No, that wasn't a typo.

Consider the following:

template 
<
    template < class Created > class CreationPolicy
> 
class CompoundClass : public CreationPolicy<MyClass>
{ 
};

Yikes, nested templates!

Indeed, by including this additional template declaration we allow the compound class to specify the template parameter itself, allowing us to declare the typedefs like this:

typedef CompoundClass< CreationNew, InitialisationZero, 
  FunctionalityHelloWorld > MyCompoundClass;
typedef CompoundClass< CreationPrototype, InitialisationZero, 
  FunctionalitySendMail > MyOtherCompoundClass;

Much neater.

Hopefully this will give an insight into the power of policy classes, as they provide a great deal of flexibility, and are not as restrictive in their use as some of the more standard OOP paradigms.

That's it for my first article. Short, yes, but hopefully it's opened a few eyes to some of the more obscure, and useful, uses for templates.

In my next article, I will be exploring more weirdness with templates, 'cause I'm like that.

Further reading

  • Modern C++ Design, by Andrei Alexandrescu, discusses Policy Class Systems along with many other "I didn't know you could do that!" C++ gems, and I strongly recommend it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

miscwriter
Systems Engineer
United Kingdom United Kingdom
My name is Chris Simpson and I'm great. If you like that sort of thing.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generalwww.boost.org & www.stlport.orgmemberTW13-Jun-03 3:00 
www.boost.org and www.stlport.org, best of the best C++ template resource web site. Tutorial, sample, idiosm, template design pattern, compiler template support status...everything you want to know about C++ template.
 
Go for it Big Grin | :-D !
QuestionCompiler recommendations?memberdog_spawn12-Jun-03 10:53 
If anyone wants to experiment with templates I recommend you use the latest version of visual studio. I have not found any other compiler that will compile anything complex. Does anyone else know a compiler that is good with templates? Thanks.
AnswerRe: Compiler recommendations?memberTW13-Jun-03 1:17 
Buy VS.2003 for compilar? Not worth!
 
Intel compilar is a lot cheaper and produce best execution code for x86 family processor. We have been using since version 6, I can say it works very well. Now we are using 7.1 for LINUX development. BCC is not a bad choice too. template can be in many ways, partial template specialization is nice to have but not a MUST have. To see what I meant, checkout the original LOKI library and see how others "workaround" it to different compilars/platform. In general, any compilar that can understand STL, is more than enough to be used in production code. In our experiences, the main different is the image size produced, no major faulty code encountered (sometimes it does happen, though).
 
Buying VS.2003 in my point of view, is helping MS to get $ to fix their own security sh*t, I cann't imagine we have to pay to get secure classes! Further more, there is no new feature/improvement for MFC/ATL at all. We are saving the $ for Roguewave Studio. We don't buy something that is academy sound but low in productivity. No bug fix patch for VS.2002 (buy the upgrade, MS said) also make us very angry at this time, VS.2004 again!?
 
VS.2003 is a shame to C/C++, blending .NET with C/C++ will soon prove to be a big mistake.
 
Smile | :)
GeneralRe: Compiler recommendations?memberWilliam E. Kempf13-Jun-03 12:08 
Anti-MS drivel. Especially in your complaint about MS's response to buy VS.2003 instead of having a "bug fix" release of VS.2002. The upgrade price from 2002 to 2003 is $29 (http://msdn.microsoft.com/vstudio/howtobuy/pricing.aspx), barely enough to cover the media and shipping/handling, and you get a whole lot more than "bug fixes".
 
And in what way is VS.2003 "a shame to C/C++"? It actually is the best compiler MS has ever put out for C/C++ developers. And why do you think "blending .NET with C/C++ will soon prove to be a big mistake"?
 
William E. Kempf
GeneralRe: Compiler recommendations?memberTW14-Jun-03 1:30 
First of all, don't assume everyone buy it from U.S. America usually enjoy better price compare to other region especially Asia. For this time, instead of recommend my company to upgrade, we are moving to LINUX with Intel C++ compiler step-by-step. We have developed MS product since MS.DOS.5, you call us anti-MS? We don't want to work with a product that get "upgrade" yearly, that have so much dependency (OS, .NET etc), we want a solution that is persist. With LINUX, it is not necessary to have the latest version to achieve a goal. We expect to see many problem arise migrating to LINUX, but having developing Windows based system for so many years, problems have never been less too.
 
Secondly, I am glad that VC++ is the best compiler, but I want to stress again being 100% compliance does not mean 100% productive. People use VC++ because of MFC/ATL, more advance user download platform SDK a MUST. Till date we still can use VC5 to work with latest SDK, although VC5 is hardly 80% compliance, you see what I mean? MS response is use .NET classes. But in this case people end up learning .NET framework, not C/C++. You should know blending VC++ with .NET is actually based on MS extension, and this is NOT what C++ is about.
 
I am not anti-MS, at some point I agreed that .NET is not a bad idea, but it is so much incompatible with C/C++ design. People should use .net nature language to consume the framework, never use C/C++. Try and see for yourself. Who knows in the future, product develop with VS need to have a chip embedded on the board to run?
 
We want to have control on our C/C++ projects, not Microsoft in anyway. I have read your work at BOOST, you should know very well what I meant, should we have boost.thread or system.thread? Your answer justify why blending C/C++ with .NET a mistake.
GeneralRe: Compiler recommendations?memberEd Din ar Qadiyyeh9-Sep-03 20:35 
Ta, TW for your shrewd observations. It's amazing how shrewish the MS-informed can be.Hmmm | :|
 
May the farce be with you.
AnswerRe: Compiler recommendations?memberWilliam E. Kempf13-Jun-03 12:11 
Many other compilers are standards compliant, or close to it. Probably the best bench mark to this can be seen by examining the Boost compiler regression test logs (though these tests are not meant to be compliance tests, as some libraries have significant "work around" code for "broken" compilers): http://boost.sourceforge.net/regression-logs/.
 
William E. Kempf
GeneralGood linkmemberdog_spawn14-Jun-03 15:46 
Thanks for that link. That will save me a lot of testing Smile | :)
 
This may be of interest to TW: most of my projects don't use ATL or MFC, but I still use Visual Studio 2003 because nothing else works for me.
GeneralRe: Good linkmemberTW15-Jun-03 4:04 
That's really interesting. Could you further explain "I still use Visual Studio 2003 because nothing else works for me.".
 
I guess your are a student, aren't you? Smile | :)
GeneralRe: Good linkmemberdog_spawn15-Jun-03 4:32 
Sure. This for example only works in Visual Studio the last time I checked.
 

template <class T> class TPointer
{
...
template<class R> TPointer<T>& operator=(const TPointer<R>& rhs) ...
...
}

 
I am looking at the link and advice you people have offered so hopefully I will find a solution. I haven't been a student for a couple of years now.

GeneralRe: Good linkmemberTW15-Jun-03 5:13 
Ever try std::auto_ptr/std::auto_ptr_ref? This two class is meant to solve the problem shown in your message. My understanding is all major C++ suite support ::std very well. Except that one is using library like boost.
 
You want to look at www.stlport.org too, if one day you are interested in BCC. SGI template for UNIX platform. Good luck! Smile | :)
AnswerRe: Compiler recommendations?memberdmarcombes3-Sep-03 3:56 
That is funny, cause most commercial and non commercial compilers are better than VS(up to 7.0) as far as templates are concerned.
Try g++, visual age, comeau, sun forte...

 
Everything should be as simple as it is, but not simpler.
Albert Einstein
GeneralBoring...memberdog_spawn3-Sep-03 7:48 
Oh great, a reply by someone who doesn't get any of the issues involved and has no evidence to backup what they say. Well done...
GeneralRe: Compiler recommendations?memberGiles13-Sep-06 2:27 
Okay, gcc back in 97 was not much good either. Visual C++ 6 is coming up ten years old. You can't slag it off. Its not got as good conformance as 2005, as it never had the time to be.
 
This whole conversation is comparing apples to oranges. I use SunForte 5-U2 on Solaris, and its got sh*t conformance. You must be talking about SunWorkshop 11, which is now a free download.
 
You are talking out of your arse.
 

 

 

GeneralGreat stuff ...memberMaximilien12-Jun-03 4:36 
I'm starting looking into Templates and other more advanced C++ stuff, and this is nice.
 
also, the book Modern C++ Design seems to be a "to-have" , will look for it.
 
Thanks.

 

Maximilien Lincourt
For success one must aquire one's self
GeneralRe: Great stuff ...membermiscwriter12-Jun-03 4:47 
Thanks. Yes, it is indeed a must-have book. But beware, it may tie your mind in knots the first time through. Chapters definitely need re-reading a couple of times before they skink in fully.
 
Chris
GeneralRe: Great stuff ...memberyarp12-Jun-03 5:31 
Severall couples of time, but very interesting anyway.
 
Yarp
http://www.senosoft.com/

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130617.1 | Last Updated 12 Jun 2003
Article Copyright 2003 by miscwriter
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid