Click here to Skip to main content
Licence 
First Posted 12 Nov 2000
Views 110,448
Bookmarked 20 times

Using templates for initialization

By | 13 Feb 2001 | Article
Use templates to initialize structures or simple member variables.

Introduction

It is quite common in coding to create a structure and then initialize it to all zeros via a memset() [or ZeroMemory()], and in the Microsoft world, it is also quite common to then set a member called cbSize to the sizeof() the structure. All this is very simple, but it can be a bit of a pain in the bum, as well as adding extra lines of code, which always is a bad thing!

Another issue is with simple class member initialization. It is not uncommon to have more than a single constructor. Forgetting to initialize variables in each has caused me problems more than once. Having an initialization function is one solution. I offer another solution.

Template initialization

With a few simple templates, we can rid ourselves of initialization problems!

template <typename T>
struct Clean : public T
{
    Clean()
    {
        ZeroMemory(this, sizeof(T));
    }
};

template <typename T>
struct Sized : public T
{
    Sized()
    {
        this->cbSize = sizeof(T);
    }
};

template <typename T>
struct CleanSized : public T
{
    CleanSized()
    {
        ZeroMemory(this, sizeof(T));
        this->cbSize = sizeof(T);
    }
};

Three templates are presented here to cover the various cases that you would encounter. Clean is if you want your structure to be just zero'd out. Sized is if you only want to set the cbSize member and CleanSized is if you want to do both.

Usage

Instead of specifying the structure directly, you just wrap it with the template. Such as the following:

    CleanSized<::SCROLLINFO> scroll_info;
    scroll_info.fMask = SIF_POS;
    scroll_info.nPos = 20;
    ::SetScrollInfo(hwnd, SB_VERT, &scroll_info, FALSE);

The first line creates the SCROLLINFO structure, but as it's wrapped by CleanSized, it will zero out the structure, as well as setting the cbSize value to the sizeof(SCROLLINFO). Simple.

You can also use this to express member variables in a class. I.e.:

class CSomeClass
{
    ...
private:
    CleanSized<::SCROLLINFO> m_scroll_info;
};

Then m_scroll_info will be initialized at the same time as the member initialization list (just before entering the constructor).

Now, this is pretty good, we can use this to clean structs in classes, but what about simple types such as int, float, enum, etc?

Well, we cannot use the above templates, as they require deriving from the template type, and as you cannot derive from simple types, this leads us to a new template:

template <typename T>
struct CleanSimple
{
    CleanSimple()
    {
        ZeroMemory(&m_t, sizeof(T));
    }

    T& AsType() {return m_t;}
    operator T&() {return m_t;}
    T* operator&() {return &m_t;}

private:
    CleanSimple(const CleanSimple& rhs);// disallow copy constructor
    operator=(const CleanSimple& rhs); // disallow operator=

    T m_t;
};

Now, you should be able to use this in the same way that you would use the simple type (see note below for an exception). Such as:

class CSomeOtherClass
{
public:
    void SomeFunction()
    {
        ++m_call_count;
        cout << "This function has been called " 
          << m_call_count << " times." << endl;
    }

private:
    CleanSimple<int> m_call_count;
};

(Note: Why the AsType() function? Well, I wish it wasn't there, and I'm not sure if it is a bug in the MS compiler or (as I know the much more likely answer is!) something I'm not thinking of, but in the case of:

CleanSimple<int> x;
int y;
y = x;

you get the following error:

error C2593: 'operator =' is ambiguous

Now, this is a bit strange as, if you change the code to:

CleanSimple<int> x;
unsigned int y;    // or float, short, or another type
y = x;

then it all works fine. Hmmm.)

OK, well this is all good and well, but this sets the variable to zero - what happens if we want to initialize it to some other value other than zero? Time for another template...

template <typename T, T t>
struct InitSimple
{
    InitSimple() : m_t(t) {}

    operator T&() {return m_t;}
    operator T&() const {return m_t;}

    T& AsType() {return m_t;}
    const T& AsType() const {return m_t;}

    T* operator&() {return &m_t;}
    const T* operator&() const {return &m_t;}

    T& operator=(const T& t) {return (m_t = t);}
    InitSimple(const InitSimple& rhs) {m_t = rhs.m_t;}

private:
    T m_t;
};

Now, this template allows you to initialize the type and value where you specify the variable. This means that you can specify in your class prototype, the default values of variables. This means that if you have multiple constructors, you don't have to remember to duplicate all the initialization for all the variables!! (This is a good thing.)

You use the class like this:

class CYetAnotherClass
{
private:
    InitSimple<int, 42> m_atltuae;
    ...
private:
    enum States
    {
        START, RUNNING, STOP
    };

    InitSimple<States, START> m_state;
};

(Note: Not that you would probably want to, but if you defined an InitSimple<> as const, then you MUST have a constructor, otherwise VC++ chokes as it doesn't think it can create a valid constructor because a const variable doesn't appear to have been initialized according to it! [I haven't bothered to check to see if this is mandated by the spec or not.])

Now I only came up with this stuff over the weekend (but who knows, I could have read an article a couple of years ago on this and this stuff finally bubbled to the top - but I don't think so !). So, there could be problems with it. Thus, if you find anything wrong, please give me a yell!

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

Paul Westcott

Web Developer

Australia Australia

Member

Born Melbourne, Australia. Mainly C++ developer (my company in Australia is called "SeaPlus Development" but is currently sitting idle). Worked on emergency service systems with Intergraph Public Safety (for New Zealand Police and Fire), on telephony applications for call centres at BP and RMG (both in Melbourne) and on Unified Messager for Avaya (in London). Worked on a casino managment system for International Game Technology (in Las Vegas) and currently working for the National Australia Bank on an equity derivatives product.

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. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
Generaladd another operator= Pinmemberahmed zahmed8:39 20 Jul '09  
GeneralProblem using a template class in a structure Pinmemberarvindb212:21 23 Jul '04  
GeneralMy solution Pinmemberrrrado23:14 23 Jan '03  
GeneralRe: My solution PinmemberJoão Paulo Figueira6:13 14 Feb '03  
GeneralRe: My solution PinsussAnonymous21:08 16 Feb '03  
GeneralRe: My solution PinmemberTW21:08 25 Feb '04  
GeneralFixed bug in CleanSimple PinmemberSimon Hughes4:20 31 Jan '02  
QuestionA sledgehammer to crack a nut? PinmemberJim Barry0:40 21 Nov '00  
AnswerRe: A sledgehammer to crack a nut? PinmemberPaul Westcott5:05 21 Nov '00  
GeneralRe: A sledgehammer to crack a nut? PinmemberPhilippe Mori12:07 24 Aug '02  
GeneralRe: A sledgehammer to crack a nut? Pinmemberahmed zahmed8:43 20 Jul '09  
AnswerRe: A sledgehammer to crack a nut? PinmemberMatthew Ellis14:59 24 Nov '00  
GeneralRe: A sledgehammer to crack a nut? PinmemberJim Barry23:53 26 Nov '00  
GeneralRe: A sledgehammer to crack a nut? PinmemberMatthew Ellis0:15 27 Nov '00  
AnswerRe: A sledgehammer to crack a nut? PinmemberAnonymous3:50 19 Feb '01  
GeneralRe: A sledgehammer to crack a nut? PinmemberPhilippe Mori11:56 24 Aug '02  
AnswerRe: A sledgehammer to crack a nut? PinmemberAnonymous4:27 14 Feb '02  
GeneralVariable names PinmemberWaleri Todorov5:00 20 Nov '00  
GeneralRe: Variable names PinmemberMichael Dunn7:23 20 Nov '00  
GeneralRe: Variable names PinmemberPaul Westcott11:55 20 Nov '00  
GeneralRe: Variable names PinmemberPhilippe Mori12:23 24 Aug '02  
GeneralAnd not names only. PinmemberMarkovAlex6:42 10 Jul '03  
GeneralI like it, but... PinmemberAndrew McKinlay4:15 17 Nov '00  
GeneralDangerous with virtual functions PinmemberOliver Anhuth22:54 14 Nov '00  
GeneralRe: Dangerous with virtual functions PinmemberPaul Westcott6:39 15 Nov '00  

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120517.1 | Last Updated 14 Feb 2001
Article Copyright 2000 by Paul Westcott
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid