C++ 0x: Visual Studio 2010 – Static assert (static_assert)

Every programmer must know about assert. Those who don’t know assert (or similar) mechanism, they’re not a real programmers :) it’s one of the most important helper for debugging. The assert library is designed to work in run time. The expression will be evaluated on program execution and test for sanity. If the express return false, then assert message will be popped up.

What if we can catch the some of the data size or some other constant constraints during compile time itself? it will reduce the overhead of bugs and assertions at run time. e.g In windows, it’s a thumb of rule that user defined messages should be defined greater than WM_USER. What if we can check a class is empty or not at compile-time itself? or the array size exceeds than a limited value?

One of the real example I can tell you from my experience is the stack size issue. By default, thread’s stack size is 1MB. I was using a big structure. it had multiple structures, array of big structures to hold the data. In fact I was using only few elements of this structure and I never taken care of the size of structure. Whenever I enter the function which declared the object of this structure crashes. I could not figure out the reason first time as the structure declaration was at the middle of the function. In this kind of situation I thought, it would be nice if compiler warns us about the structure size. But in my understanding compiler has limitation over these kind of application parameters. But those who are so much cared about this kind of situation can make use of static assert.

As many of you know, most of the C++ 0x standard specification was directly taken or got inspired by boost library. You can see a bunch of examples and demonstration of these features in the boost library as well.

See the code snippet below

// StaticAssert.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iosfwd>
#include <type_traits>

const int WM_USER = 1024;
const int MY_CUSTOM_MESSAGE = 1; // invalid value

class EmptyClass
{
};

class CPoint
{
	int x;
	int y;
	CPoint() { x = y = 0; }
};

struct BigStruct
{
	char Dummy[4194304];
};

int _tmain(int argc, _TCHAR* argv[])
{
	static_assert( MY_CUSTOM_MESSAGE > WM_USER , "Custom message should be defined greater than WM_USER" );
	static_assert( std::tr1::is_pod<CPoint>::value, "This is not a plane old data type" );
	static_assert( !std::tr1::is_empty<EmptyClass>::value, "The class should not be empty" );
	static_assert( sizeof( BigStruct ) < 1024*1024, "The structure size exceeds stack size" );
	return 0;
}

You Should Avoid Partial Initialization of Objects

Recently a code came to me for a review. I’m not exposing the real code but just scribbling a sample code like as it is.

#include <iostream>

using namespace std;
#define LOG_ERROR(msg) cerr<<msg<<endl
// Just a manager class. the members and other details are irrelevant here
class CManager
{ };
class CRender
{
private:
// Status whether the object is initialize or not
bool m_bInitialized;
CManager* m_pManager; // Manager Pointer
public:
// Ctor
CRender( CManager* pManager )
{
    if( !pManager )
    {
        LOG_ERROR(“Invalid pointer to Manager”);
        return; // You shouldn’t return at this point. This is dangerous
    }
    m_pManager = pManager;
    m_bInitialized = false;
    }
    // Initialize function
    bool Initialize()
    {
        if( !m_bInitialized )
        {
            cout<<”Do processing”
            m_bInitialized = true;
        }
        else
           LOG_ERROR(“Object already initialized”);
       return m_bInitialized;
    }
};

int main( int argc, char* argv[] )
{
    CRender rend(NULL);
    rend.Initialize();
    return 0;
}

Effective C++ also explains this scenario in prolific manner. An object should be constructed and destructed fully. Partial Initialization will make some unexpected behavior. The Initialize function can be called any number times from outside world. If we pass a NULL to the pointer, the object creation will not be complete since some of the significant members are omitted from its initialization.

Of course there are many ways defend write solid code. But still many people are not thinking in that way. You can also check for the m_pManager pointer many times in the functions where we are using it. In some trusted applications or classes, we will not validates the input because we are quite sure about the parameter passing.

In this case the the m_bInitializedis the catch which is initialized with some unknown values (it may vary depends on the compilers and configuration) we we can’t predict. Now in this case the Object will be in truble with “Default” constructor of that member. Note that this is the case of intrinsic data types. For the objects of some classes, the default Initialization will be done using default constructor or specified constructor in the Initialization list. Your code defines the behavior of your program.

Also I need to add one more point; if we are assigning something inside the ctor, that will be operator= operation than (copy) contruction.

Construction happens in the initialization list. For those members which is not specified in the initialization list, the compiler will initialize them with default constructor or value(compiler specific. for Visual C++, in the debug mode, the default value for initialization is 0xCD per byte).

CRender( CManager* pManager ) : m_pManager(pManager)

{

}

The above code is initialization and the previous one is rather assignment. The initialization really makes sense while you are using some heavy class or containers which does some heavy initializations. Containers will allocate memory of a default number of elements to avoid frequent allocation and de-allocation.

Suppose we have a vector of type int as class member and we are going to initialize it as follows.

CRender( const vector<int>& points )
{
    m_Points = vec; // calling operator= of vector
}

In the above code, the m_Points member will be initialized with default constructor even if didn’t specify that. Inside the body of the constructor, it is calling “operator=” of vector. So for the initialization of a member we have pay more CPU cycles since it will do some allocations, de-allocation or relocation depends on the input. But the following code can save some CPU cycle and thus the code will be a bit faster.

CRender( const vector<int>& points ) : m_pPoints(points)
{
    // Do rest of the processing
}

The above one has a serious drawback while we are using multiple constructors for the object where we need to specify it in the initialization list of every ctors. In that case it can be moved to a common function where you can do the initialization even if you pay more CPU cycles.

So never ever throw exceptions or return from constructors or destructors because it will show some unexpected behaviours because of the partial construction or destruction of objects (members).