Skip to content

CWG2946 [temp.over.link] Dependent call equivalence in non-ADL cases #631

Open
@hubert-reinterpretcast

Description

@hubert-reinterpretcast

Full name of submitter (unless configured in github; will be published with the issue): Hubert Tong

Reference (section label): [temp.over.link]

Link to reflector thread (if any): N/A

Issue description:
It is unclear whether the resolution of CWG 1321 meant to cover cases where ADL is not in scope (e.g., because lookup found a callable object or a block-scope extern declaration). For example, the wording says that the following should compile 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 (whereas the use of C in N::f can be satisfied). That is, the wording allows for using the contradictory logic that something false is implied by something true.

There is implementation divergence (Clang, GCC, and MSVC reject; EDG accepts); https://godbolt.org/z/79YfEP6Wr:

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));

Additionally, a call with a parenthesized unqualified-id as the callee is not considered a "dependent call" (https://wg21.link/temp.dep.general#2). The leaves us with the original problem of Core Issue 1321 for such call expressions.

Suggested resolution:
Retain the resolution of CWG 1321 for ADL cases.
Use the unique result of name lookup for the non-function case.
Some "invention here":
Use the results of name lookup (plus any dependent using declarations) in the class scope case.
Use the set of block scope declarations (including using declarations) in the block scope case.
Where the operand is a parenthesized unqualified-id not matching the above cases, use the namespace scope (i.e., ignoring the specific declarations and any using directives) in addition to the name.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions