Topic: Implicit filter through... ?
Author: "werasm" <w_erasm@telkomsa.net>
Date: Wed, 12 Jul 2006 10:24:33 CST Raw View
> 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 ]
Author: Michiel.Salters@tomtom.com
Date: Thu, 13 Jul 2006 09:29:58 CST Raw View
Frederick Gotham wrote:
> 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 ]
Author: "werasm" <w_erasm@telkomsa.net>
Date: Thu, 13 Jul 2006 09:27:11 CST Raw View
werasm wrote:
> 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 ]
Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Tue, 4 Jul 2006 23:24:42 GMT Raw View
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 ]
Author: stephen.clamage@sun.com (Steve Clamage)
Date: Wed, 5 Jul 2006 02:10:23 GMT Raw View
Frederick Gotham wrote:
> 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@sun.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 ]
Author: Frederick Gotham <fgothamNO@SPAM.com>
Date: Wed, 5 Jul 2006 11:08:37 CST Raw View
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()
{
/* 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 ]
Author: "Victor Bazarov" <v.Abazarov@comAcast.net>
Date: Wed, 5 Jul 2006 14:58:00 CST Raw View
Frederick Gotham wrote:
> 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()
?
> {
> /* 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.
> 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 ]
Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Wed, 5 Jul 2006 21:09:20 GMT Raw View
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.
--
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 ]
Author: v.Abazarov@comAcast.net ("Victor Bazarov")
Date: Wed, 5 Jul 2006 21:49:49 GMT Raw View
Frederick Gotham wrote:
> 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 ]
Author: "Bob Bell" <belvis@pacbell.net>
Date: Wed, 5 Jul 2006 17:08:38 CST Raw View
Frederick Gotham wrote:
> 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 ]
Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Thu, 6 Jul 2006 03:20:55 GMT Raw View
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.
--
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 ]
Author: stephen.clamage@sun.com (Steve Clamage)
Date: Thu, 6 Jul 2006 15:32:28 GMT Raw View
Frederick Gotham wrote:
> 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@sun.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 ]