Using (return val of) member function as default parameter of member function

11 November, 2009 § 2 Comments

C++ allows the programmer to do some really cool things. When writing code I try to follow the Google C++ Style Guide, so I haven’t gotten much experience with the fringe areas of default parameters. A question was recently asked on the comp.lang.c++.moderated usenet group where the OP wanted to place a member function as the default argument, a la:

class foo {
 int getInteger();
 void doSomething(int i = getInteger()) { }
};

Many of the responses said that he should overload doSomething as a nullary function and call the original doSomething with the return value of the member function. Within most of these comments was one from Neil Butterworth, who mentioned that the reason this isn’t possible is because the this pointer is not available until the body of the function. He offered that the OP could make getInteger a static function.

class foo {
 static int getInteger();
 void doSomething(int i = getInteger()) { }
 };

And if you don’t believe him, you can use the Comeau C/C++ Online Compiler to see for yourselves.

I thought this was really cool. While I may not have a use for it at the moment, it is questions like these that are great conversation starters. About a month ago I subscribed to the clcm mailing list and I now recommend it to others as a way to learn different uses of C++ and interesting conversations about the language.

Compile-time virtual function calls in C++

21 August, 2009 § 7 Comments

C++ templates provide some really fascinating abilities, one of which is compile-time virtual function calls. WTL, the Windows Template Library, uses compile-time virtual function calls when deriving types. In this post, I will cover what I mean when I say “compile-time virtual function calls”, and how they create faster code and smaller executables.

By far, below is the most common use of templates within C++ code:

namespace std {
   template <typename T>
   class vector {
      /* ... */
   }
}
std::vector<int> primeNumbers;

But what if we wanted to derive our own type, with a templated class being the base type? See this example:

template <typename T>
class WindowImpl {
   int id_of_windowImpl;
   static LPCTSTR GetWindowCaption() { return NULL; }
   void DrawWindow() {
      LPCTSTR windowTitle = T::GetWindowCaption();
      /* Draw window and place title at top of UI */
   }
} 

Did you notice that there was no mention of the keyword virtual? This is where our little trick comes in. Let’s say we wanted to make our own boring derivation of Window, one that has the title of “Basic Window”. We could simply do this:

class BasicWindowImpl : WindowImpl<BasicWindowImpl> {
   int id_of_basicWindowImpl;
   static LPCTSTR GetWindowCaption() {
      return _T("Basic Window");
   }
}

BasicWindowImpl<BasicWindowImpl> basicWindow;

When the code is compiled, the static method GetWindowCaption will be called on the derived type. If the method isn’t implemented in the derived type, then the C++ lookup rules state that it will look deeper in the class and find the base implementation that returns NULL.

Also, this whole practice is made possible since immediately following the colon, the type has been declared and the typename can be used as a template parameter.

What does this mean in terms of efficiency/footprint?

First a short high level overview on how virtual functions are implemented. When a method inside of a class is declared virtual, a special data type is added to the class. This data type stores function offsets from the base of the class. When a call is made using a base type, this virtual function table (vftbl or vtable for short) is referenced and the memory address of the function is retrieved and executed.

Each instance of a class will hold a pointer to this table (often called a vpointer). This pointer is usually initialized at the end of the constructor by some hidden code that your C++ compiler generates.

On a 32-bit machine with 32-bit ints and no virtual functions: basicWindow is 8 bytes (4 bytes for each int that it holds).

On a 32-bit machine with 32-bit ints and virtual functions: basicWindow is 12 bytes (the same 8 bytes plus 4 bytes for the vpointer). Also, there is another 4 bytes used for the vtable and it’s one function pointer that is stored and pointing to BasicWindowImpl::GetWindowCaption.

In summary, by using compile-time virtual function calls, the sample code cuts it’s memory use in half. The vtable pointer does not consume much memory, but if there were 1,024 BasicWindowImpl instances created, then an extra 4kb of data would be unnecessarily used. Also, there is no need to look up the function address in the table due to the static linking of the overriden function at compile-time.

This brings you a smaller and faster executable by making your compiler work just a little harder.

Ordering of Include Statements to Reduce Hidden Dependencies

23 July, 2009 § 2 Comments

The Google C++ Style Guide says that #include statements should be ordered in the following way (if you are writing foo2.cc):

  1. dir2/foo2.h (preferred location — see details below).
  2. C system files.
  3. C++ system files.
  4. Other libraries’ .h files.
  5. Your project’s.h files.

The goal of this is to reduce hidden dependencies within header files. My question is, shouldn’t system files be included after library/project files? I would think that there is a guarantee that the system files aren’t going to include other library/project files, so wouldn’t the following order make more sense to find hidden dependencies?

  1. dir2/foo2.h (preferred location — see details below).
  2. Your project’s.h files.
  3. Other libraries’ .h files.
  4. C system files.
  5. C++ system files.

Non-member non-friend functions vs private functions

28 June, 2009 § 5 Comments

Herb Sutter has said that the most object oriented way to write methods in C++ is using non-member non-friend functions. Should that mean that I should take private methods and turn them into non-member non-friend functions? Any member variables that these methods may need can be passed in as parameters.

Example (before):

class Number {
 public:
  Number( int nNumber ) : m_nNumber( nNumber ) {}
  int CalculateDifference( int nNumber ) { return minus( nNumber ); }
 private:
  int minus( int nNumber ) { return m_nNumber - nNumber; }
  int m_nNumber;
};

Example (after):

int minus( int nLhsNumber, int nRhsNumber ) { return nLhsNumber - nRhsNumber; }
class Number {
 public:
  Number( int nNumber ) : m_nNumber( nNumber ) {}
  int CalculateDifference( int nNumber ) { return minus( nNumber ); }
 private:
  int m_nNumber;
};

Am I on the right track? Should all private methods be moved to non-member non-friend functions? What should be rules that would tell you otherwise?

I’ve asked the question on Stack Overflow. Feel free to leave a response there so I can better track responses and award credit.

Update to a previous post

22 June, 2009 § 1 Comment

I’ve updated the post titled, “C++ Trick: Removing the need for Forward Declarations“. Further reading of The C++ Programming Language by  Bjarne Stroustrup has pointed me to a partial explanation [1]:

For reasons that reach into the pre-history of C, it is possible to declare a struct and a non-structure with the same name in the same scope. For example:

struct stat {  /* ... */  };
int stat( char* name, struct stat* buf);

In that case, the plain name (stat) is the name of the non-structure, and the structure must be referred to with the prefix struct. Similarly, the keywords class, union (§C.8.2), and enum (§4.8) can be used as prefixes for disambiguation. However, it is best not to overload names to make that necessary.

That explains part of it. My assumption stands that because you are declaring that this name refers to a typename, then you will not need to forward declare it. I haven’t tried it yet, but I assume you can interchange `class` with `typename` just as well to declare that this is a type you are referring to.

[1] B. Stroustrup. The C++ Programming Language: 3rd Edition. Page 104.

Where Am I?

You are currently browsing entries tagged with c-plus-plus at JAWS.

Follow

Get every new post delivered to your Inbox.

Join 99 other followers