This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-10-26
[Moved to DR at the October, 2012 meeting.]
Consider the following example:
int g(int); template <class T> decltype(g(T())) f(); int g(); template <class T> decltype(g(T())) f() { return g(T()); } int i = f<int>();
Do the two fs declare the same function template? According to 13.7.7.2 [temp.over.link] paragraph 5,
Two expressions involving template parameters are considered equivalent if two function definitions containing the expressions would satisfy the one definition rule (6.3 [basic.def.odr]), except that the tokens used to name the template parameters may differ as long as a token used to name a template parameter in one expression is replaced by another token that names the same template parameter in the other expression.
The relevant portion of 6.3 [basic.def.odr] paragraph 5 says,
in each definition of D, corresponding names, looked up according to 6.5 [basic.lookup], shall refer to an entity defined within the definition of D, or shall refer to the same entity, after overload resolution (12.2 [over.match]) and after matching of partial template specialization (13.10.4 [temp.over]), except that a name can refer to a const object with internal or no linkage if the object has the same literal type in all definitions of D, and the object is initialized with a constant expression (7.7 [expr.const]), and the value (but not the address) of the object is used, and the object has the same value in all definitions of D
This could be read either way, since overload resolution isn't done at this point. Either we consider the result of the unqualified name lookup and say that the expressions aren't equivalent or we need a new rule for equivalence and merging of dependent calls.
Proposed resolution (December, 2011):
Change 13.7.7.2 [temp.over.link] paragraph 5 as follows:
Two expressions involving template parameters are considered equivalent if two function definitions containing the expressions would satisfy the one definition rule (6.3 [basic.def.odr]), except that the tokens used to name the template parameters may differ as long as a token used to name a template parameter in one expression is replaced by another token that names the same template parameter in the other expression. For determining whether two dependent names (13.8.3 [temp.dep]) are equivalent, only the name itself is considered, not the result of name lookup in the context of the template. If multiple declarations of the same function template differ in the result of this name lookup, the result for the first declaration is used. [Example:
template <int I, int J> void f(A<I+J>); // #1 template <int K, int L> void f(A<K+L>); // same as #1 template <class T> decltype(g(T())) h(); int g(int); template <class T> decltype(g(T())) h() // redeclaration of h() uses the earlier lookup { return g(T()); } // ...although the lookup here does find g(int) int i = h<int>(); // template argument substitution fails; g(int) // was not in scope at the first declaration of h()—end example] Two expressions...
Change 13.8.3 [temp.dep] paragraph 1 as follows:
...In an expression of the form:
postfix-expression ( expression-listopt )
where the postfix-expression is an
id-expressionunqualified-id, theid-expressionunqualified-id denotes a dependent name if
any of the expressions in the expression-list is a pack expansion (13.7.4 [temp.variadic]),
any of the expressions in the expression-list is a type-dependent expression (13.8.3.3 [temp.dep.expr]), or
if the unqualified-id
of the id-expressionis a template-id in which any of the template arguments depends on a template parameter.if an operand...
Change 13.8.4.2 [temp.dep.candidate] paragraph 1 as follows:
For a function call
that depends on a template parameterwhere the postfix-expression is a dependent name, the candidate functions are found using the usual lookup rules (6.5.3 [basic.lookup.unqual], 6.5.4 [basic.lookup.argdep], 6.5.5 [basic.lookup.qual]) except that:
For the part of the lookup using unqualified name lookup (6.5.3 [basic.lookup.unqual])
or qualified name lookup (6.5.5 [basic.lookup.qual]), only function declarations from the template definition context are found.For the part of the lookup using associated namespaces (6.5.4 [basic.lookup.argdep]), only function declarations found in either the template definition context or the template instantiation context are found.
If
the function name is an unqualified-id andthe call would be ill-formed or would find a better match had the lookup within the associated namespaces considered all the function declarations with external linkage introduced in those namespaces in all translation units, not just considering those declarations found in the template definition and template instantiation contexts, then the program has undefined behavior.