I have code that compiles fine with VC9 (Microsoft Visual C++ 2008 SP1) but not with GCC 4.2 (on Mac, if that matters). If I pile on enough qualifiers and keywords I can force it to work in GCC but this doesn't seem right.
Here's a minimal code sample exhibiting my problems:
template< typename N >
struct B {
typedef N n_type; // can derived class access typedef?
void foo() {} // can derived class access function?
};
template< typename N >
struct D : public B<N> {
typedef B<N> b_type;
typedef typename b_type::n_type bn_type;
void f1( n_type ) {} // ERROR: 'n_type' has not been
// declared
void f2( typename B<N>::n_type ) {} // OK, verbose
void f3( b_type::n_type ) {} // ERROR: 'struct B<N>::n_type' is
// not a type
void f4( typename b_type::n_type ) {}开发者_如何学编程 // OK, verbose
void f5( bn_type ) {} // OK, verbose typedefs
void f6() { foo(); } // ERROR: there are no arguments to
// 'foo' that depend on a template
// parameter, so a declaration of
// 'foo' must be available
void f7() { b_type::foo(); } // OK, verbose
};
Am I wrong to expect a template class derived from another template class to be able to use inherited typedefs and functions directly? Is there a better way to do this than what I've come up with so far?
Am I wrong to expect a template class derived from another template class to be able to use inherited typedefs and functions directly?
Yes, this will not generally work as you expect it. The C++ name lookup rules specify that a name is only searched in a templated base classes if it depends on a template parameter (if it is a "dependent name"). If a name does not depend on a template parameter it isn't searched there. (Also see this C++ FAQ Lite entry)
To call functions from a dependent base class the most easy way is to use this->
, since this
is always implicitly a dependent name:
void f6() { this->foo(); }
See the C++ FAQ Lite § 35.18-20 and the C++ Templates FAQ.
Two-phase name lookup is a tricky part of C++ that many compilers (and coders) get wrong. Suffice it to say, GCC is being more correct (as per the C++ specification) than MSVC is here, and no, there is no better way to do what you want.
There is no type n_type. There is (or may be) a type with that name dependent on N. So no, you can't do what you want.
Here are a few links that could help understand why it needs a typename
keywords to be used:
- Stan Lippman's blog
- StackOverflow.com
- comeaucomputing
Seems that GCC is 'doing it right'
精彩评论