Topic: DR: ADL rules for template functions consider unrelated context


Author: Dragan Milenkovic <dragan@plusplus.rs>
Date: Tue, 23 Jun 2009 10:18:36 CST
Raw View
This DR is refers to:
   - [temp.names] 14.2/2 in C++03, 14.3/2 in C++0x
   - [temp.arg.explicit] 14.8.1/6 in C++03, 14.9.1/8 in C++0x

The rules for "func_x" in "func_x<Type>(foo)" state that it should
be treated as a template name only if the name "is known to refer to
a template", otherwise the expression is parsed as a relational
expression.

These rules are fine, or at least seem fine until ADL gets introduced.
In my opinion, the merged rules are only a workaround and not
a sound solution.

It is dependent upon names in possibly completely unrelated
namespaces with possibly completely different meaning to determine
whether "func_x" should be treated as a template or not.
As a consequence, one can either clobber the global namespace,
or abandon providing ADL semantics together with templates.

The issues whether "func_x<Type>" should be treated as a template-id
or a relational expression are purely syntactic, and shouldn't
consider an unrelated context that can be in control of another
library and another developer. If an unrelated context is considered,
it shouldn't be used only as a "stepping stone" for another goal.

Maybe introducing a syntax such as "template func_x<Type>"
would solve the problem and allow ADL to be consistently used
with template functions as it is with non-template functions.

My motivation was the following example:

namespace zxc {

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

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

}

// I don't want this line!
template <typename Y> void func_x();

int main() {
     zxc::Foo foo;

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

Here, "func_int" and "func_x<int>" should be treated equally, at
least with respect to ADL.

For the global "func_x" one of the following stands:
   - Either it was written by the same person who designed "Foo",
     in which case this person could have skipped ADL altogether
     and write "::func_x" to do the desired work or delegate to
     a member of Foo.
   - Or it was written by someone else for different purposes,
     in which case it can change anytime (if being completely
     unrelated doesn't stress the problem well enough).

--
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                      ]