Reputation: 8239
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
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
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
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