Mihai Todor
Mihai Todor

Reputation: 8239

Undefined template argument for base class

I am quite sure I have read the reason why the compiler cannot cope with this code somewhere on SO, but, after a few hours of searching, I still can't find it. Here is the relevant code:

#include <iostream>

template <typename T>
class base
{
};

class derived : base<derived::myStruct>
{
public:
    struct myStruct
    {
    };
};

int main ()
{
    return 0;
}

The problem is that the parser first tries to generate the base<derived::myStruct> specialization before parsing derived, and, thus, I get this error: "error C2065: 'myStruct' : undeclared identifier". As a silly trick, I noticed that VS2010 stops complaining if I pre-declare struct myStruct; just above class derived. In my opinion, myStruct should be bound inside derived and this code should throw the same error:

#include <iostream>

template <typename T>
class base
{
};

struct myStruct;

class derived : base<derived::myStruct>
{
public:
    struct myStruct
    {
    };
};

int main ()
{
    return 0;
}

Update: gcc-4.5.1 is able to throw the expected error, so, I guess the above is a bug in VS2010...

Upvotes: 4

Views: 881

Answers (3)

Jesse Good
Jesse Good

Reputation: 52365

derived::myStruct is simply an incomplete type at this point. Your second example should also not work, unfortunately the MSVC compiler accepts a lot of malformed template code. One work around is to use an intermediate class to make sure the type is complete:

template <typename T>
class base
{
};

class middle
{
public:
    struct myStruct
    {
    };
};

class derived : public middle, base<middle::myStruct>
{
};

int main ()
{
    return 0;
}

Upvotes: 2

Ambroz Bizjak
Ambroz Bizjak

Reputation: 8095

A workaround is to declare myStruct outside of derived.

#include <iostream>

template <typename T>
class base
{
};

struct derived_myStruct
{
};

class derived : base<derived_myStruct>
{
public:
    typedef derived_myStruct myStruct;
};

int main ()
{
    return 0;
}

In more complex cases where derived is a template class, derived_myStruct would too be a template class, with the same template paramerters (or just a subset), and you would pass those through.

Upvotes: 1

Dietmar K&#252;hl
Dietmar K&#252;hl

Reputation: 153792

In C++ you can only refer to names once they are defined. Since derived is clearly not, yet, defined when you refer to a class nested inside derived to define a base class, this cannot work. The exception for things being sort of declared after they are accessed is for function bodies of members defined within the class definition: these are treated as if they are actually defined after the class definition.

Upvotes: 1

Related Questions