C++ Trick: Removing the need for Forward Declarations

18 June, 2009 § 3 Comments

C++ is known to have lots of tricks. This is seen by some as a powerful asset and by others as a reason to stray away. I’m always fascinated by learning new features of C++ and have fun finding out more all the time.

During a recent code review, I noticed the  following code:

foo.h

#ifndef FOO_H
#define FOO_H

class foo {
};

#endif

bar.h

#ifdef BAR_H
#define BAR_H

class bar  {
 class foo* m_pFoo;
 bar();
};

#endif

bar.cpp

#include "bar.h"
#include "foo.h"

bar::bar() : m_pFoo( new foo )
{
} 

Notice anything  odd? How about line 5 in bar.h?

It turns out that there is no forward declaration needed in bar.h for the foo type if you write your declaration like so. The reason that this works is by prepending the typename with ‘class’, you are explicitly telling the compiler that foo is a type, and you are declaring a pointer to this type. If you did not prepend the declaration with class, then the compiler would have no way to know if you meant to multiply a variable named foo by another variable named m_pFoo.

You may have seen this idiom more with structs, like so:

struct POINT { 
int x;
int y;
};

struct POINT topLeft;

And so it turns out there is more! You can even replace that same line 5 with:

struct foo* m_pFoo;

This is because the C++ Standard says that a class can be declared as a struct and it is still a class. There is no difference when declaring a class or struct in C++. The only difference comes when the type is defined, in which struct causes bases and members to be public by default. [1]

I don’t recommend that you use this trick in production code, as it is likely to confuse other members of your team, and there is no performance savings by not typing the class name one more time and another semicolon, but you can definitely use this to stump one of your friends about your inner-knowledge of C++.

Update (June 22, 2009): The ability to do this comes from the pre-history of C. Within C and C++, you can create a struct/class and a non-struct/class with the same name, such as:

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

When you use the struct/class, you have to prefix it with the keyword struct/class to disambiguate between the names. [2]

[1] D. Abrahams, A. Gurtovoy. C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond. Page 25.
[2] B. Stroustrup. The C++ Programming Language: 3rd Edition. Page 104.

Finally will execute, even after return

7 January, 2009 § Leave a comment

How’s this for weird looking code?

public static void RunSnippet()
{
    var y = testFinally();
    if( y == 99 )
    {
        WL("It is 99");
    }
    else
    {
        WL("It is 6");
    }
}

public static int? testFinally()
{
    int? x = 99;
    try
    {
        return x;
    }
    finally
    {
        x = 6;   
    }
    return x;
}

What happens? testFinally will return 99. If you changed the finally block to set x equal to null, the same result will happen. When there is a finally block, the function will not return until after the finally block has finished, regardless of any code following it. The second return statement is never reached. Also, you cannot return from a finally block, since control flow statements cannot be made in a finally block.

The code above was written with SnippetCompiler, a really nice free tool to have at your side when you want to test something out but don’t want to create a new solution in Visual Studio.

Extension Methods on Null Instances

6 January, 2009 § 1 Comment

I was reading some blog posts and came across one from Brad Wilson about a year ago. Extension methods are a pretty cool construct, allowing you to add instance methods to sealed classes easily. This brings with it a way to write code that can cause some weird readability issues. Often used is the static method String.IsNullOrEmpty. With an extension method you could add that method to instances and the code will work fine, even if the object is null.

Here’s a code sample:

using System;

public static class MyExtensions
{
   public static bool IsNullOrEmpty(this string str)
   {
      return String.IsNullOrEmpty(str);
   }
}

Now all Strings will have a method to check if they are null or empty. You can see that the readability would make you think that a NullReferenceException would be thrown if the object is null and the method wouldn’t get called. This is the odd part of extension methods.

The method will still get called, and the code will work like normal.

public static void Main()
{
   string str = null;
   bool strIsNull = str.IsNullOrEmpty();
   System.Console.WriteLine(strIsNull);
}

C++ Function Try Blocks

14 November, 2008 § 1 Comment

Will it compile?

That is the question for this post. Suppose you have a class definition and constructor with an object initializer list like the following:

class CObject
{
   CFoo foo;
   CBar bar;
};

CObject::CObject() : foo(2), bar(3) {}

« Read the rest of this entry »

Where Am I?

You are currently browsing the Will It Compile? category at JAWS.

Follow

Get every new post delivered to your Inbox.

Join 100 other followers