I got recently bitten by (simplified)
struct Base {
typedef char T;
};
template<typename T>
struct Foo : Base {
T x[50]; // This is Base::T, not the template parameter
};
In other words a class member name hides a template parameter (even if coming from a base class, thus not being totally evident in the local context).
Making some experiment I found however that:
struct Base {
typedef char T;
};
template<typename T, typename B>
struct Foo : B {
T x[50]; // This T is the template parameter,
// even passing Base as B
};
The only way out I can think to is to give ugly template parameter names and also means that it's impossible to write safely a template without using reserved names (as class used in the template could clash parameter names... note that a lot of C++ code uses uglyfied names for private members).
PS: I didn't dig in the standard about the issue but both g++ and clang++ agree on this behavior so I don't think it's a bug.
PPS: In the real code the template parameter being hidden was named tid
, and was an integer and not a type. -Wall
was not enough to notifiy about the hiding and I discovered it after a couple of hours of debugging with valgrind.
This rule (specified in [temp.local]/9) is subject of an open core language issue created over 11 years ago - core issue #459. The CWG discussed this thoroughly. About the intent, Mike Miller mentions that
The rationale for the current specification is really very simple:
“Unless redeclared in the derived class, members of a base class are also considered to be members of the derived class.” (10 [class.derived] paragraph 2)
In class scope, members hide nonmembers.
That's it. Because template parameters are not members, they are hidden by member names (whether inherited or not). I don't find that “bizarre,” or even particularly surprising.
Rationale:
We have some sympathy for a change, but the current rules fall straightforwardly out of the lookup rules, so they're not “wrong.” Making private members invisible also would solve this problem. We'd be willing to look at a paper proposing that.[..]
The CWG decided not to consider a change to the existing rules at this time without a paper exploring the issue in more detail.
Unfortunately no such paper has been written yet, and so the rule persists until today.