Template parameter name hiding
Asked Answered
C

1

15

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.

Corkhill answered 31/3, 2015 at 7:5 Comment(7)
Did you try it with different compilers? It would be nice to know whether this is implementation related, a carelessness in the standard or an actual intention.Paulenepauletta
@Paulenepauletta This is standardized behavior and certainly not a carelessness.Polymorphonuclear
maybe because dependent name and independent name. see this maybe help you.Turnheim
one letter variables are a bad idea. I am even avoiding one letter template variables. They hide intent. One letter does not reveal anything to the poor bastard that has the read the code. That poor bastard being yourself included. The idea is to avoid getting bitten.Cagliari
@PhilipStuyck: 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 discoverd it after a couple of hours of debugging with valgrind.Corkhill
In the first example the compiler doesn't need to wait until the template arguments are known, the actual type T is already in scope; in the second T is unambiguously the template parameter, as there is no way of knowing beforehand that it might refer to a type T in the base class.Approachable
I can understand that you get bitten like this, even with longer names the base class might be in a different file, here it is easy because everything is close together. Easy to miss.Cagliari
P
7

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.

Polymorphonuclear answered 31/3, 2015 at 7:40 Comment(2)
Thanks for the answer. It is indeed standardized, but still an issue.Paulenepauletta
For anyone interested, two years later, the issue is still open and the status remains the same.Assentation

© 2022 - 2024 — McMap. All rights reserved.