Title
Equivalency of dependent calls
Status
cd3
Section
13.7.7.2 [temp.over.link]
Submitter
Jason Merrill

Created on 2011-05-18.00:00:00 last changed 123 months ago

Messages

Date: 2012-10-15.00:00:00

[Moved to DR at the October, 2012 meeting.]

Date: 2011-12-15.00:00:00

Proposed resolution (December, 2011):

  1. Change 13.7.7.2 [temp.over.link] paragraph 5 as follows:

  2. 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...

  3. Change 13.8.3 [temp.dep] paragraph 1 as follows:

  4. ...In an expression of the form:

      postfix-expression ( expression-listopt )

    where the postfix-expression is an id-expression unqualified-id, the id-expression unqualified-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-expression is a template-id in which any of the template arguments depends on a template parameter.

    if an operand...

  5. Change 13.8.4.2 [temp.dep.candidate] paragraph 1 as follows:

  6. For a function call that depends on a template parameter where 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 and the 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.

Date: 2022-09-25.18:08:42

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.

History
Date User Action Args
2014-03-03 00:00:00adminsetstatus: drwp -> cd3
2013-05-03 00:00:00adminsetstatus: dr -> drwp
2012-11-03 00:00:00adminsetmessages: + msg4160
2012-11-03 00:00:00adminsetstatus: ready -> dr
2012-09-24 00:00:00adminsetmessages: + msg3873
2012-02-27 00:00:00adminsetstatus: tentatively ready -> ready
2012-01-17 00:00:00adminsetstatus: review -> tentatively ready
2011-05-18 00:00:00admincreate