c++templateslanguage-lawyername-lookupname-hiding

Template parameter name hiding


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
};

What is the rationale (if any) behind this apparently absurd rule?

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.


Solution

  • 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.