Click here to Skip to main content
15,892,298 members
Articles / Programming Languages / C++
Article

Using templates for initialization

Rate me:
Please Sign up or sign in to vote.
3.50/5 (3 votes)
13 Feb 2001 154.4K   20   38
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


Written By
Web Developer
Australia Australia
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.

Comments and Discussions

 
Generaladd another operator= Pin
TheGreatAndPowerfulOz20-Jul-09 8:39
TheGreatAndPowerfulOz20-Jul-09 8:39 
GeneralProblem using a template class in a structure Pin
arvindb2123-Jul-04 2:21
arvindb2123-Jul-04 2:21 
GeneralMy solution Pin
rrrado23-Jan-03 23:14
rrrado23-Jan-03 23:14 
GeneralRe: My solution Pin
João Paulo Figueira14-Feb-03 6:13
professionalJoão Paulo Figueira14-Feb-03 6:13 
GeneralRe: My solution Pin
Anonymous16-Feb-03 21:08
Anonymous16-Feb-03 21:08 
GeneralRe: My solution Pin
TW25-Feb-04 21:08
TW25-Feb-04 21:08 
GeneralFixed bug in CleanSimple<T> Pin
31-Jan-02 4:20
suss31-Jan-02 4:20 
QuestionA sledgehammer to crack a nut? Pin
Jim Barry21-Nov-00 0:40
Jim Barry21-Nov-00 0:40 
AnswerRe: A sledgehammer to crack a nut? Pin
Paul Westcott21-Nov-00 5:05
Paul Westcott21-Nov-00 5:05 
GeneralRe: A sledgehammer to crack a nut? Pin
Philippe Mori24-Aug-02 12:07
Philippe Mori24-Aug-02 12:07 
GeneralRe: A sledgehammer to crack a nut? Pin
TheGreatAndPowerfulOz20-Jul-09 8:43
TheGreatAndPowerfulOz20-Jul-09 8:43 
AnswerRe: A sledgehammer to crack a nut? Pin
Mr Matt Ellis, Esq24-Nov-00 14:59
Mr Matt Ellis, Esq24-Nov-00 14:59 
GeneralRe: A sledgehammer to crack a nut? Pin
Jim Barry26-Nov-00 23:53
Jim Barry26-Nov-00 23:53 
GeneralRe: A sledgehammer to crack a nut? Pin
Mr Matt Ellis, Esq27-Nov-00 0:15
Mr Matt Ellis, Esq27-Nov-00 0:15 
Hi Jim! What can I say? I get around...

Well, it serves me right for trying to be smart! Moral: it you look anything up, make sure you look it up in the right book. Anyway, it's nice to have the correct behaviour well defined.

Thanks!
Matt

AnswerRe: A sledgehammer to crack a nut? Pin
19-Feb-01 3:50
suss19-Feb-01 3:50 
GeneralRe: A sledgehammer to crack a nut? Pin
Philippe Mori24-Aug-02 11:56
Philippe Mori24-Aug-02 11:56 
AnswerRe: A sledgehammer to crack a nut? Pin
14-Feb-02 4:27
suss14-Feb-02 4:27 
GeneralVariable names Pin
20-Nov-00 5:00
suss20-Nov-00 5:00 
GeneralRe: Variable names Pin
Michael Dunn20-Nov-00 7:23
sitebuilderMichael Dunn20-Nov-00 7:23 
GeneralRe: Variable names Pin
Paul Westcott20-Nov-00 11:55
Paul Westcott20-Nov-00 11:55 
GeneralRe: Variable names Pin
Philippe Mori24-Aug-02 12:23
Philippe Mori24-Aug-02 12:23 
GeneralAnd not names only. Pin
MarkovAlex10-Jul-03 6:42
MarkovAlex10-Jul-03 6:42 
GeneralI like it, but... Pin
17-Nov-00 4:15
suss17-Nov-00 4:15 
GeneralDangerous with virtual functions Pin
14-Nov-00 22:54
suss14-Nov-00 22:54 
GeneralRe: Dangerous with virtual functions Pin
Paul Westcott15-Nov-00 6:39
Paul Westcott15-Nov-00 6:39 

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

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