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.

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;
}

No comments: