Title
Dependent call equivalence in non-ADL cases
Status
open
Section
13.7.7.2 [temp.over.link]
Submitter
Hubert Tong

Created on 2024-10-30.00:00:00 last changed 3 weeks ago

Messages

Date: 2024-11-05.22:41:37

Suggested resolution (incomplete):

  1. Change in 13.7.7.2 [temp.over.link] paragraph 5 as follows, adding bullets:

    ... For determining whether two dependent names (13.8.3 [temp.dep]) are equivalent, the following rules apply:
    • If name lookup finds a non-function, that entity is considered.
    • Otherwise, if name lookup finds a set of block-scope declarations (including using-declarations), that set is considered.
    • Otherwise, if the name appears in a class scope, the lookup set for the name, merged with any dependent using-declarations, is considered.
    • Otherwise, if the parenthesized name is the postfix-expression of a dependent call, the name itself and the namespace scope is considered, not the result of name lookup.
    • Otherwise, if the name is the postfix-expression in a dependent call, only the name itself is considered, not the result of name lookup.
    [Note 5: If such a dependent name is unqualified, it is looked up from a first declaration of the function template (13.8.1 [temp.res.general]). —end note]
  2. Change in 13.8.3.1 [temp.dep.general] paragraph 2 as follows:

    A dependent call is an expression, possibly formed as a non-member candidate for an operator (12.2.2.3 [over.match.oper]), of the form:
      postfix-expression ( expression-listopt )
    
    where the postfix-expression is an a (possibly parenthesized) unqualified-id and
    • any of the expressions in the expression-list is a pack expansion (13.7.4 [temp.variadic]), or
    • any of the expressions or braced-init-lists in the expression-list is type-dependent (13.8.3.3 [temp.dep.expr]), or
    • the unqualified-id is a template-id in which any of the template arguments depends on a template parameter.
Date: 2024-10-30.00:00:00

(From submission #631.)

It is unclear whether the resolution of issue 1321 covers cases where argument-dependent lookup is not used, for example because a callable object or a block-scope extern declartion was found. There is implementation divergence (EDG accepts, others reject) for the following example:

  template <typename ...T>
  struct Blob : T ... {
    using T::operator() ...;
  };
  template <typename T> constexpr bool IsInt = false;
  template <> constexpr bool IsInt<int> = true;
  template <typename T> concept C = IsInt<T>;
  namespace N {
    constexpr auto f() {
      int f(int);
      return [](auto x) requires C<decltype(f(x))> { return true; };
    }
  }
  namespace M {
    constexpr auto f() {
      short f(int);
      return [](auto x) requires C<decltype(f(x))> || (sizeof(x) == 4) {};
    }
  }
  template <typename ...T>
  constexpr Blob<T ...> blobber(T ...) { return {}; }
  static_assert(blobber(N::f(), M::f())(0));

The wording says the example is well-formed, because the use of C in N::f subsumes the use of C in M::f, despite the fact that the use of C in M::f can never be satisfied.

Additionally, a call of the form (f)(x,y) (with a parenthesized postfix-expression) is not considered a dependent call per 13.8.3.1 [temp.dep.general] paragraph 2, leaving the issue addressed by issue 1321 open for such cases.

History
Date User Action Args
2024-10-30 12:32:51adminsetmessages: + msg7866
2024-10-30 00:00:00admincreate