[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Is it g++ bug with "typename"?
From: |
Grizlyk |
Subject: |
Re: Is it g++ bug with "typename"? |
Date: |
Sun, 11 Mar 2007 21:23:07 +0300 |
Paul Pluzhnikov wrote:
>
>> I am thinking: why if i will comment lines marked with '#' in the
>> following
>> example, all will be compiled, else will not:
>
> You'll get better answers if you reduce your test case (or state
> that you couldn't).
I have posted complete compileable example and can not reduce it because can
not detect the point of error, so I have posted all parts. I have marked
probably error's line by "#" sign:
public:
typedef c_Second Second;
typedef typename c_Second::Third Third; //#1
typedef typename c_Second::Forth Forth; //#2
>> 11.cpp:57: error: no type named 'Second' in 'class
>> 11.cpp:57: error: Pxx::Puser::First<int, unsigned int>'
It is really wrong error message of gcc due to "type named 'Second'" is
declared in the class. My question was: why if I declare only
typedef c_Second Second;
all will be OK? Is it standard behaviour (unexplainable for me) or it is gcc
specific error? It is important for desing of my classes. If it is error and
it is error in "Second::subtype" why gcc point to "Second", not to
"Second::subtype"? It is really not easy to find a cause of the error
looking for "Second".
***
By the way, i think we must not get any errors here, because all have been
declared correctly, if we will trace compilation pass we will see the
following:
1. class template Pxx::First declaration
namespace Pxx{
template <
class Tobj,
class c_Second,
class Tuint=uint
>
class First
{
public:
typedef c_Second Second;
typedef typename c_Second::Third Third; //#1
typedef typename c_Second::Forth Forth; //#2
here "Second" will be used as forward declaration of the class name, no
sizeof(Second) needed, so we even can compile here concrete code returning
references to "Second" and so on, the name can not be resolved at the point
of template declaration.
"typename c_Second::Third" is forward declaration of the class name, can not
be resolved at the point of template declaration.
2. class template Pxx::Second declaration
namespace Pxx{
template <
class Tobj,
class c_First,
class c_Forth,
class c_Third,
class Tuint=uint
>
class Second
{
public:
typedef c_First First;
typedef c_Forth Forth;
typedef c_Third Third;
//derived Second
typedef typename c_First::Second c_Second;
here the same, "typename c_First::Second" is forward declaration of the
class name, can not be resolved at the point of template declaration.
3. some classes forward declarations
namespace Puser{
template <class Tobj,class Tuint> class First;
template <class Tobj,class Tuint> class Second;
template <class Tobj,class Tuint> class Third;
template <class Tobj,class Tuint> class Forth;
here the same: "First<>" and "Second<>" are forward declarations of the
class name, can not be resolved at the point of template declaration.
4. class template Puser::First declaration
template <
class Tobj,
class Tuint=uint
>
class First:
public Pxx::First<
Tobj,
Second<Tobj,Tuint>,
Tuint
>
{
typedef Pxx::First<
Tobj,
Second<Tobj,Tuint>,
Tuint
>
Tparent;
now
"typename Tparent::Second" is instantiated as "Second<Tobj,Tuint>"
>> 11.cpp:57: error: no type named 'Second' in 'class
>> 11.cpp:57: error: Pxx::Puser::First<int, unsigned int>'
What is the problem here? Nothing.
"typename Tparent::c_Second::Third" is still forward declaration of the
class name, can not be resolved at the point of template Puser::First
declaration, because we have no body of "Second<Tobj,Tuint>" here, only
forward declaration of "Second<Tobj,Tuint>".
5. class template Puser::Second declaration
template <
class Tobj,
class Tuint=uint
>
class Second:
public Pxx::Second<
Tobj,
First<Tobj,Tuint>,
Forth<Tobj,Tuint>,
Third<Tobj,Tuint>,
Tuint
>
{
typedef Pxx::Second<
Tobj,
First<Tobj,Tuint>,
Forth<Tobj,Tuint>,
Third<Tobj,Tuint>,
Tuint
>
Tparent;
now
"typename Tparent::First" is instantiated as "First<Tobj,Tuint>"
"typename Tparent::First::Second" already _can_ be found during declaration
of "Puser::Second" because we have already defined body of
"First<Tobj,Tuint>" here: ("typename Tparent::Second" is instantiated as
"Second<Tobj,Tuint>") so
"typename Tparent::First::Second" is well defined as "Second<Tobj,Tuint>"
(as itself).
Beause "Second<Tobj,Tuint>" is self name, the name can be used not only as
forward declaration of "Second<Tobj,Tuint>", but yet as name of "class with
completely defined body", because compiler must allow "multipass" for
class's types untill the class's "};" sign encountered. But in the example
we do not need that, it is enough to treat the name as forward declaration
of the class.
We also can write in "Pxx::Second" like this
//subtype of derived Second
typedef typename c_First::Second::First c_Second_subtype_First;
and
"typename Tparent::c_Second_subtype_First" is
"First<Tobj,Tuint>" (the same as "typename Tparent::First")
6. instance of Puser::First<int>
using Puser::First;
First<int> test;
"typename Puser::First<int>::Tparent::Second" is
"typename Puser::Second<int>"
"typename Puser::First<int>::Tparent::Third" is
"typename Puser::Second<int>::Third<int>" //#1
"typename Puser::First<int>::Tparent::Fourth" is
"typename Puser::Second<int>::Fourth<int>" //#2
All completely defined.
>
> The error message appears to be mis-leading.
> Here is what EDG parser reports:
>
> "junk.cc", line 57: error: incomplete type is not allowed
> typedef typename c_First::Second c_Second;
> ^
It is interesting why "typename c_First::Second" is incomplete?
> detected during:
> instantiation of class "Pxx::Second<Tobj, c_First, c_Forth,
> c_Third, Tuint> [with Tobj=int,
> c_First=Pxx::Puser::First<int, uint>,
> c_Forth=Pxx::Puser::Forth<int, uint>,
> c_Third=Pxx::Puser::Third<int, uint>, Tuint=uint]" at
> line 106
> instantiation of class "Pxx::Puser::Second<Tobj, Tuint> [with
> Tobj=int, Tuint=uint]" at line 14
> instantiation of class "Pxx::First<Tobj, c_Second, Tuint> [with
> Tobj=int, c_Second=Pxx::Puser::Second<int, uint>,
> Tuint=uint]" at line 81
> instantiation of class "Pxx::Puser::First<Tobj, Tuint> [with
> Tobj=int, Tuint=uint]" at line 141
>
What is "EDG parser"?
--
Maksim A. Polyanin
http://grizlyk1.narod.ru/cpp_new