Topic: Template friend injection - a language defect or not?


Author: Dragan Milenkovic <dragan@plusplus.rs>
Date: Thu, 4 Jun 2009 21:52:19 CST
Raw View
Please help me with the following problem.

namespace zxc {

     class Foo {
      public:
         friend int func_int(const Foo &) { /*...*/ }

         template <typename X>
         friend X func_x(const Foo &) { /*...*/ }
     };

}

int main() {
     zxc::Foo foo;

     func_int(foo);     // #1 OK, found by ADL and friend injection
     func_x<int>(foo);  // #2 PROBLEMS!!!
}

Here is what the Standard has to say about #2 and how it bothers me.

3.4.2
We all know this. It states that in case of a function call
with an "unqualified name", additional namespaces are searched
and functions that are otherwise hidden, such as injected friend,
may be found.

One source of confusion is the term "unqualified name".
Am I right to think that both 'func_int' and 'func_x<int>'
are "unqualified names"?

(To explain why I said "source of confusion" - it's related
to my bug report http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34870)

14.2/2 and 14.8.1/6
Only recently has someone pointed to these paragraphs. The first
one is a one-liner, the second one is just a note. Their impact
is however is big. Apparently, they state that "func_x" must
be _known_ to refer to a template, even before any ADL is
considered, even before it is successfully parsed as
a function call expression. This is _only_ because
of the syntax being ambiguous.

It goes as far as to give an example how a template function
in completely unrelated namespace (or a global namespace),
with the only relevant properties being that it has the same
name, and that it's visible in the current context,
can make a difference and treat #2 as a function call,
which results in func_x being found through ADL.

I think this is ugly. My first point is that whether
"func_x<int>(foo)" is a function call should _not_ be
dictated by a completely unrelated entity in another
namespace. It might be a global name in another library,
with completely different meaning, and may be changed
by the maintainer anytime.

My second point is that semantically, func_int and
func_x<int> should be treated the same. Currently
it is not possible, but _only_ because of syntax problems.
If any other solution fails, at least the syntax should
be invented that would allow it. Currently it is
not possible to simply say "call a template function func_x<int>"
Also, it's not possible to call zxc::func_x<int>(foo) either,
since this name is only visible through ADL.

This has been bothering me for a long time (just look
at the bug report). I hope someone helps get things straight.

Thanks.

--
Dragan

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]