 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Frederick Gotham Guest
|
Posted: Wed Jul 05, 2006 4:24 am Post subject: Implicit filter through... ? |
|
|
When dealing with normal classes (i.e. non-template classes), typedef's
filter through from the base class to the derived class, e.g.:
class Base {
public:
typedef int SpecialType;
};
class Derived : public Base {
public:
SpecialType obj;
};
int main()
{
Derived obj;
obj.obj = 8;
}
However, if I introduce template-ness into it, then g++ gives me the
following compilation error:
`SpecialType' does not name a type
(perhaps `typename Base<T>::SpecialType' was intended)
Should the code compile without error? Here it is:
template<class T>
class Base {
public:
typedef int SpecialType;
};
template<class T>
class Derived : public Base<T> {
public:
SpecialType obj;
};
int main()
{
Derived<int> obj;
obj.obj = 8;
}
--
Frederick Gotham
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Steve Clamage Guest
|
Posted: Wed Jul 05, 2006 7:10 am Post subject: Re: Implicit filter through... ? |
|
|
Frederick Gotham wrote:
| Quote: | When dealing with normal classes (i.e. non-template classes), typedef's
filter through from the base class to the derived class, e.g.:
class Base {
public:
typedef int SpecialType;
};
class Derived : public Base {
public:
SpecialType obj;
};
int main()
{
Derived obj;
obj.obj = 8;
}
However, if I introduce template-ness into it, then g++ gives me the
following compilation error:
`SpecialType' does not name a type
(perhaps `typename Base<T>::SpecialType' was intended)
Should the code compile without error? Here it is:
template<class T
class Base {
public:
typedef int SpecialType;
};
template<class T
class Derived : public Base<T> {
public:
SpecialType obj;
};
int main()
{
Derived<int> obj;
obj.obj = 8;
}
|
A base class exists in a scope that surrounds a derived class. When
looking up a name used in a derived class, base class names are visible
if they are not hidden by a declaration of the same name in the derived
class.
Your first example works because of this name lookup rule.
For templates, the name lookup rules are different.
A dependent base class is one that depends on a template parameter of
the derived class. Dependent base classes are not automatically searched
for declarations. The reason for the rule is that a specialization of
the base class might exist that doesn't look anything like the primary
template. For example, Base<int> could be an explicit specialization
that does not declare a type SpecialType.
In your second example, Base<T> depends on the template parameter of
Derived<T>. Since Base<T> is not automatically searched, no declaration
of SpecialType is visible.
If you want to inherit from a dependent base class, you must qualify the
reference:
typename Base<T>::SpecialType obj;
You need the "typename", because a name from a dependent base class is
not taken to be a type unless you say it is a type.
Not all compilers enforce these rules. You might find a compiler that
compiles your original second example, but that compiler would not be
standard-conforming.
Non-dependent base classes don't have these special rules, because there
cannot be an alternative definition for them:
Example 3:
class Base {
public:
typedef int SpecialType;
};
template<class T>
class Derived : public Base { // Base does not depend on T
public:
SpecialType obj; // OK
};
Example 4:
template<class U>
class Base {
public:
typedef int SpecialType;
};
template<class T>
class Derived : public Base<int> { // Base does not depend on T
public:
SpecialType obj;
};
---
Steve Clamage, stephen.clamage (AT) sun (DOT) com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Frederick Gotham Guest
|
Posted: Wed Jul 05, 2006 5:08 pm Post subject: Re: Implicit filter through... ? |
|
|
Steve Clamage posted:
| Quote: | If you want to inherit from a dependent base class, you must qualify
the
reference:
typename Base<T>::SpecialType obj;
|
Thank you for your detailed explanation, it was very helpful.
I am currently writing very template-heavy code, and to my dismay, it has
become very ugly and verbose. Where I would like to be able to have:
SpecialType Derived::Foo()
{
/* Function Body */
}
I have to have:
template<class T>
typename Base<T>::SpecialType Derived<T>::Foo()
{
/* Function Body */
}
Are there any intentions to change the Standard in an effort to make
template code less verbose? I like the "template namepaces" proposal very
much, but I don't think it will solve ALL of the problems. With my code
the way it is now, I run out of horizontal screen space a lot.
--
Frederick Gotham
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Victor Bazarov Guest
|
Posted: Wed Jul 05, 2006 8:58 pm Post subject: Re: Implicit filter through... ? |
|
|
Frederick Gotham wrote:
| Quote: | Steve Clamage posted:
If you want to inherit from a dependent base class, you must qualify
the reference:
typename Base<T>::SpecialType obj;
Thank you for your detailed explanation, it was very helpful.
I am currently writing very template-heavy code, and to my dismay, it
has become very ugly and verbose. Where I would like to be able to
have:
SpecialType Derived::Foo()
|
'SpecialType' name isn't known in this context, in fact this is what
you *need* to have:
Base::SpecialType Derived::Foo()
?
| Quote: | {
/* Function Body */
}
I have to have:
template<class T
typename Base<T>::SpecialType Derived<T>::Foo()
{
/* Function Body */
}
|
You can re-declare 'SpecialType' in Derived, and maybe shave off
a couple of keystrokes:
using typename Base<T>::SpecialType;
or
typedef typename Base<T>::SpecialType SpecialType;
Of course, at best you will have saved the 'typename' keyword. You
still need to say
template<class T>
Derived<T>::SpecialType Derived<T>::Foo() ...
So, I think you're a bit overstating your troubles.
| Quote: | Are there any intentions to change the Standard in an effort to make
template code less verbose? I like the "template namepaces" proposal
very much, but I don't think it will solve ALL of the problems. With
my code the way it is now, I run out of horizontal screen space a lot.
|
Use typedef's more often.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Bob Bell Guest
|
Posted: Wed Jul 05, 2006 11:08 pm Post subject: Re: Implicit filter through... ? |
|
|
Frederick Gotham wrote:
| Quote: | Victor Bazarov posted:
SpecialType Derived::Foo()
'SpecialType' name isn't known in this context, in fact this is what
you *need* to have:
Base::SpecialType Derived::Foo()
Would it be possible to introduce something similar to Koenig lookup,
whereby the return type of a member function is looked up in the scope of
the class... ? Sounds good to me.
|
One problem that immediately springs to mind (and I don't know if it's
a deal breaker or not) is that you're expecting the compiler to finish
parsing the return type before even seeing that it is the return type
of a member function.
Another problem is ambiguities:
typedef char SpecialType;
struct Base {
typedef int SpecialType;
SpecialType F();
};
SpecialType Base::F(); // int or char?
Bob
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Frederick Gotham Guest
|
Posted: Thu Jul 06, 2006 2:09 am Post subject: Re: Implicit filter through... ? |
|
|
Victor Bazarov posted:
| Quote: | SpecialType Derived::Foo()
'SpecialType' name isn't known in this context, in fact this is what
you *need* to have:
Base::SpecialType Derived::Foo()
|
Would it be possible to introduce something similar to Koenig lookup,
whereby the return type of a member function is looked up in the scope of
the class... ? Sounds good to me.
--
Frederick Gotham
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Victor Bazarov Guest
|
Posted: Thu Jul 06, 2006 2:49 am Post subject: Re: Implicit filter through... ? |
|
|
Frederick Gotham wrote:
| Quote: | Victor Bazarov posted:
SpecialType Derived::Foo()
'SpecialType' name isn't known in this context, in fact this is what
you *need* to have:
Base::SpecialType Derived::Foo()
Would it be possible to introduce something similar to Koenig lookup,
whereby the return type of a member function is looked up in the
scope of the class... ? Sounds good to me.
|
I don't think it's possible to introduce at this time. This code would
either silently change behaviour or become broken after such change in
the language:
typedef char C;
struct B {
static C const cc = 0; // OK -- static char const???
C foo(); // at this time 'C' is 'char' here (or is it?)
struct C {
int a;
C(int aa) : a(aa) {}
};
};
C B::foo() { // Is it still 'char' here? Or is it now B::C?
return cc;
}
int main() {
B b;
return sizeof(b.foo() - 1); // possible change in behaviour
}
I can think of a worse scenario.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Frederick Gotham Guest
|
Posted: Thu Jul 06, 2006 8:20 am Post subject: Re: Implicit filter through... ? |
|
|
Steve Clamage posted:
| Quote: | If you want to inherit from a dependent base class, you must qualify
the
reference:
typename Base<T>::SpecialType obj;
|
Would things not be better if the following were allowed?
template<class T>
class Base {
public:
typedef int SpecialType;
};
template<class T>
class Derived : public Base<T> {
public:
SpecialType obj;
};
Why was it decided that this shouldn't work? I know that some compilers
will allow it.
--
Frederick Gotham
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Steve Clamage Guest
|
Posted: Thu Jul 06, 2006 8:32 pm Post subject: Re: Implicit filter through... ? |
|
|
Frederick Gotham wrote:
| Quote: | Steve Clamage posted:
If you want to inherit from a dependent base class, you must qualify
the
reference:
typename Base<T>::SpecialType obj;
Would things not be better if the following were allowed?
template<class T
class Base {
public:
typedef int SpecialType;
};
template<class T
class Derived : public Base<T> {
public:
SpecialType obj;
};
Why was it decided that this shouldn't work? I know that some compilers
will allow it.
|
For the reason that I explaind in my original post. Any instance of
Base<T> can be explicitly specialized. If you want Derived<T> to pick up
a declaration from Base<T>, you have to say so, meaning that you accept
the consequences of an explicit specialization of Base<T> that does not
have the characteristics you expect.
By default, you don't get surprises.
As Victor Barazov pointed out, you can make the coding easier to write
and probably easier to read by using more typedefs.
---
Steve Clamage, stephen.clamage (AT) sun (DOT) com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
werasm Guest
|
Posted: Wed Jul 12, 2006 4:24 pm Post subject: Re: Implicit filter through... ? |
|
|
| Quote: | Should the code compile without error? Here it is:
template<class T
class Base {
public:
typedef int SpecialType;
};
template<class T
class Derived : public Base<T> {
public:
SpecialType obj;
};
|
I think the reason for this (error) is 2 phased lookup. In the 1st
phase nondependent names are looked-up, and in the 2nd phase dependent
names are looked up.
This allows for the compiler to emit diagnostics on non-dependent names
without explicit instantiation of the applicable template. The
baseclass is question is what one calls a dependent base class (depends
on T). The standard specifies that nondependent names (SpecialType) are
not looked up in dependent base classes. The reason for this (briefly)
is that the meaning of the name (in the base) can change during
specialisation, causing the derived to break. C++ Templates has a good
example of this on page 137.
In the above case, SpecialType should not be found and the compiler
should emit a diagnostic if it implements 2 phased lookup.
Regards,
Werner
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
werasm Guest
|
Posted: Thu Jul 13, 2006 3:27 pm Post subject: Re: Implicit filter through... ? |
|
|
werasm wrote:
| Quote: | specialisation, causing the derived to break. C++ Templates has a good
example of this on page 137.
|
Beg my pardon, the book "C++ Templates" by Vandervoorde/Josuttis has an
example on page 137. I hope this is clearer now.
Regards,
Werner
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Guest
|
Posted: Thu Jul 13, 2006 3:29 pm Post subject: Re: Implicit filter through... ? |
|
|
Frederick Gotham wrote:
| Quote: | Would it be possible to introduce something similar to Koenig lookup,
whereby the return type of a member function is looked up in the scope of
the class... ? Sounds good to me.
|
There have been proposals to add a new declaration syntax, e.g.
C::foo() : SpecialType {
}
Personally, I'd say "use auto" because at that scope, the compiler can
simply look
up the declaration. The auto can only be interpreted as starting a
member definition,
and we don't overload by return type. i.e.
auto C::foo( ) { /*...*/ }
This reuses the auto keyword, with the same meaning as in the decltype
proposals:
"Compiler, you already know the type. I've told you. Don't make me type
it twice."
HTH,
Michiel Salters
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|