About Me

My photo
I'm a colonist who has declared war on machines and intend to conquer them some day. You'll often find me deep in the trenches fighting off bugs and ugly defects in code. When I'm not tappity-tapping at my WMD (also, known as keyboard), you'll find me chatting with friends, reading comics or playing a PC game.

Wednesday, February 27, 2008

const pointers and typedef

(Reader Level : Beginner)
(Knowledge assumptions : Pointers, typedef, std::vector...)

Sometimes we create our own types using the typedef keyword in C++. For eg;
typedef std::vector<int> INTVECTOR;

If we write : const INTVECTOR myVector;
It is the same as : const std::vector<int> myVector;
This means that the type (in this case, a vector of ints) itself is constant and we can't do stuff like this:
myVector.push_back(10);

Let's look at a typedef for a pointer.
typedef int* INTPTR

If we write : const INTPTR pInt;
Is it equivalent to writing? : const int* pInt;
To answer that we need to think about what these two statements syntactically mean.

In the former statement, we are saying that the type (in this case, the integer pointer) itself is constant and that we can't change it in anyway. That statement prevents us from doing stuff like this: pInt++;

In the second statement, we are informing the compiler that the value that the pointer "points" to is constant.
That means we CAN do : pInt++;
But we can't do : *pInt = 20;

In other words,
const INTPTR pInt; is equivalent to int* const pInt;

Monday, February 25, 2008

Defining a user-defined type within a templated class definition

(Reader Level : Intermediate)
(Knowledge assumptions : Classes, Templates, Structures...)

Ever tried declaring a class, structure, array or an enum within a templated class? Perhaps, the code could be something like this:
template<class T>
class MyClass
{
public:
struct MyStruct
{
T m_d1, m_d2, m_d3;
};

const MyStruct& GetStructure() const;

private:
MyStruct m_struct;
};

template<class T>
const MyClass<T>::MyStruct& MyClass<T>::GetStructure() const
{
return m_struct;
}

MyStruct is not a general-purpose structure. It's used primarily for MyClass. So, it makes sense to scope it within MyClass itself. However, this code will not compile. The following errors were reported by the Microsoft Visual Studio 2005 compiler.
warning: 'MyClass::MyStruct' : dependent name is not a type
error: syntax error : missing ';' before '&'
error: missing type specifier - int assumed. Note: C++ does not support default-int
fatal error: unable to recover from previous error(s); stopping compilation


Clearly the cause of this lies in the fact that the compiler can't discern the type of MyStruct in the GetStructure() definition. A look at the standards provides the solution. The relevant citation is from Section 14.6:
"When a qualified-id is intended to refer to a type that is not a member of the current instantiation (14.6.2.1) and its nested-name-specifier depends on a template-parameter (14.6.2), it shall be prefixed by the keyword typename, forming a typename-specifier."

The revised GetStructure() definition for MyClass should be as follows:
template<class T>
const typename MyClass<T>::MyStruct& MyClass<T>::GetStructure() const
{
return m_struct;
}

Tuesday, February 12, 2008

The Pimpl pattern

(Reader Level : Beginner)
(Knowledge assumptions : Classes, Pointers...)

The Private Implementation (Pimpl) pattern allows the implementation of a whole interface without the need to recompile the modules which use it. As with most design patterns, this pattern can best be explained with an example. Let's say that we have a class named Student. Our Student class is very popular in our project because many other classes use it. The header file of the Student class, "Student.h" may be as follows:
#ifndef STUDENT_HEADER
#define STUDENT_HEADER

#include <string>

class Student
{
private:
std::string m_name;
};

#endif

We may have many classes that contain instances of Student. For example, a Subject class may have an aggregation of Students. So, each of the classes that contain Student(s) would probably have to include "Student.h". Now let's say that at some point in time, colleges allow students to carry mobile phones freely (I know that's not likely. :D). Now, our Student will have a contact number that we might want to record. Professors already had mobiles all along. So, let's say that we already have a class named ContactNo that stores all types of numbers, be they Landline, Mobile or Pagers. "Student.h" becomes...
#ifndef STUDENT_HEADER
#define STUDENT_HEADER

#include <string>
#include "ContactNo.h"

class Student
{
private:
std::string m_name;
ContactNo m_contactNo;
};

#endif

After making the relevant changes, we need to do a full re-compile of the source. To our dismay, we might find that the compile time has become unbearably long. Why? It's because we included "Contact.h" in our popular "Student.h". With that one simple change, the header files of all the classes that used to just include "Student.h" will now also include "Contact.h". If our Student was that popular, then this might mean a lot of unnecessary inclusions. To add insult to injury, the contact number of the Student might never even be used by many classes. For example, our Subject class would have no reason to know the contact number of the Students who take that subject. That's why m_contactNo is a private member of Student. You might think that the entire situation is a bit contrived but I assure you its not and there can be situations where you might desperately be seeking a way to reduce compile times, especially in the case of large projects. This is where the Pimpl pattern comes in. Basically, what we need to somehow achieve is the removal of "ContactNo.h" from "Student.h". What we do is take the private implementation of the class (in our case, m_contactNo of Student) and pack it into a simple internal structure. A pointer to this structure, called an opaque pointer or d-pointer is then made a private member of the class. We also need to take care of dynamically creating and destroying the implementation structure for every object of the wrapping class.

This is then our "Student.h" file with the Pimpl pattern.
#ifndef STUDENT_HEADER
#define STUDENT_HEADER

#include <string>

class Student
{
private:
std::string m_name;
struct PIMPL; //Forward declaration.
PIMPL* pimpl; //The opaque pointer.

public:
Student();
~Student();
};

#endif

Our "Student.cpp" file could be:
#include "Student.h"
#include "ContactNo.h"

//Private Implementation structure.
struct Student::PIMPL
{
ContactNo m_contactNo;
};

Student::Student()
{
pimpl = new PIMPL;
}

Student::~Student()
{
if(pimpl)
delete pimpl;
}

If we want to access the contact number of the student internally we do it as pimpl->m_contactNo. Now that we've seen how useful the Pimpl pattern can be, let's talk about its downside. By using the Pimpl pattern, our code has become a little more complex (less readable anyway) and we've also got to do a dynamic allocation for every instance of Student that is created. For large objects with relatively fewer instances, this probably won't be an issue but for small objects with several instances, Pimpl may not fit the bill.