Proposal: Allow using injected class name when template name is in scope

  • Thread starter Johannes Schaub (litb)
  • Start date
J

Johannes Schaub (litb)

The following is not currently well-formed:

template<typename>
struct base { void f() { } };

struct A : base<int> {
void f(int) { }
};

int main() {
A a;
a.base::f();
}

It would seem to be beneficial to make this work by finding the inherited
injected class name of base<int> in A. But currently it is ill-formed
because that name does not denote the same entity as the name found in the
context of the entire postfix-expression, which refers to the base template.

To make this work, could one not get rid of the part of 3.4.3/1 that says
"... and templates whose specializations are types."? When is a class-
template name or a template alias name ever going to be valid before a "::"?
So if this part would be removed, the global base template would be ignored,
and only the injected class name in A would be found and the program would
be valid.
 
V

Victor Bazarov

The following is not currently well-formed:

template<typename>
struct base { void f() { } };

struct A : base<int> {
void f(int) { }
};

int main() {
A a;
a.base::f();
}

It would seem to be beneficial to make this work by finding the inherited
injected class name of base<int> in A. But currently it is ill-formed
because that name does not denote the same entity as the name found in the
context of the entire postfix-expression, which refers to the base template.

To make this work, could one not get rid of the part of 3.4.3/1 that says
"... and templates whose specializations are types."? When is a class-
template name or a template alias name ever going to be valid before a "::"?
So if this part would be removed, the global base template would be ignored,
and only the injected class name in A would be found and the program would
be valid.

What problem does it solve that cannot be solved using some other ways?

In your case, try adding a 'using' declaration in 'A':

struct A : base<int> {
void f(int) {}
using base<int>::f;
};

and then omit 'base::' in the call...

V
 
J

Johannes Schaub (litb)

Victor said:
What problem does it solve that cannot be solved using some other ways?

In your case, try adding a 'using' declaration in 'A':

struct A : base<int> {
void f(int) {}
using base<int>::f;
};

and then omit 'base::' in the call...

It just seems intuitive to me if it worked. Because if you place the "base"
template in a non-global namespace, it suddenly works because "base" is then
not found by unqualified lookup anymore. Such a difference causes confusion
I think.
 
V

Victor Bazarov

It just seems intuitive to me if it worked. Because if you place the "base"
template in a non-global namespace, it suddenly works because "base" is then
not found by unqualified lookup anymore. Such a difference causes confusion
I think.

After I posted my reply I thought a bit, and this occurred to me: 'base'
is not a member/base name, is it? 'base<int>' would be, no? I can't
claim full understanding of the lookup rules in the current Standard,
and even less in the upcoming one...

V
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top