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.

Tuesday, October 14, 2008

Template Parameter friends

(Reader Level : Intermediate)
(Knowledge assumptions : templates, friend)


The problem:

Currently, the C++ standard does not allow you to write code like this:
template<class T1, class T2>

class MyClass
{
friend class T1;
friend class T2;
};
You can’t make the template parameter of a class be a friend of that particular class. This might seem a reasonable requirement but the language does not allow you to do this, at least not directly.

The workaround:
In order to accomplish what we require here’s a quick workaround.

For the GCC compiler:-
#define MAKE_FRIEND(T) friend class MakeFriend<T>::Result

template<class T>
class MakeFriend
{
public:
typedef T Result;
};

template<class T1, class T2>
class MyClass
{
MAKE_FRIEND(T1);
MAKE_FRIEND(T2);
};

For Microsoft's compiler:-

#define MAKE_FRIEND(T) friend MakeFriend<T>::Result

template<class T>
class MakeFriend
{
public:
typedef T Result;
};

template<class T1, class T2>
class MyClass
{
MAKE_FRIEND(T1);
MAKE_FRIEND(T2);
};

Note the use of the 'class' keyword in the MAKE_FRIEND macro for the GCC compiler but not for the Microsoft compiler. If either T1 or T2 is not a class, then your compiler will complain. For example, if you try to instantiate an object with:
MyClass<SomeClass, int> myClassObj;
then the GCC compiler will say error: invalid type ‘int’ declared ‘friend’. But that makes sense, doesn’t it?

The code above has been tested on GCC 3.4.5 and on Microsoft Visual Studio 2008 (using the Microsoft Compiler).

2 comments:

cle said...

Unfortunately this feature seems to be forbidden by the C++ Standard. Those compilers seem to accept your code errorneously.

The Comeau compiler will complain, for instance.

Angelo said...

You are right. The Comeau compiler won't allow you to use this trick. Thanks for pointing it out.