On Sun, Oct 11, 2020 at 10:16 AM Григорий Шуренков via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
C++ has rather complex name lookup rules for unqualified function calls that involve argument-dependent lookup and may lead to surprising results. And from time to time there appear proposals to fix those rules. This is one of such proposals.

Most of the time invoking ADL is not what a user wanted. However, ADL also has legitimate use cases: operators and "customization points" (swap, begin, end are examples).  The idea of the proposal is that we can mark customization points with operator keyword and deprecate ADL for all functions that are not marked with such keyword.

That is if ADL was triggered for an unqualified function call and a function was found via ADL that was not an operator, then a compiler may issue a warning. Currently it's not feasible to have such a warning, because we cannot not discriminate between "good" ADL and "bad" ADL.

I like this general user experience; it sounds very similar to `override`. But then wouldn't it make more sense to introduce a contextual keyword similar to `override`?

    void swap(A& fst, A& snd) adl { ... }

One difficulty you might have with this is that you'll have to specify what happens in a case like
    void swap(A& fst, A& snd);
    void swap(A& fst, A& snd) adl;  // valid to add the keyword later?
    void swap(A& fst, A& snd) adl { ... }  // valid to repeat the keyword later?
We don't have this problem for `explicit` and `override` and `final` because they are usable only on member functions, which must have a single declaration (inside the class body) and a single definition.
We don't have this problem for `noexcept` and `const` because they are part of the type system.
We do have this problem for `static`, and I would guess that you should copy whatever `static` does.

Declaration of a custom swap function then will look like this:
void operator swap (A& fst, A& snd);

Your reuse of existing keyword `operator` smells to me like it's going to cause parsing problems.
    struct S {
        operator foo();  // conversion function
        void operator foo();  // member function with the ADL marker — is this even valid?
        static void operator foo();  // static member function with the ADL marker — is this even valid?
        friend void operator foo();  // friend with the ADL marker
    };
    void operator operator+(S);  // free function with the ADL marker
    void operator-(S);  // free function without the ADL marker — you imply that the ADL marker would be implicitly added anyway?

If you're going to add a contextual marker for ADL, my kneejerk reaction is that I'd prefer it also provide some symmetric way to mark a function (operator or otherwise) as not findable via ADL.

However, that might be hard because of how ADL works. The biggest practical problem with ADL is not that it sometimes finds unexpected best-matches (although that is a minor problem). The biggest problem is that it looks for them in the first place. The lookup is the thing that can trigger hard un-SFINAE-able errors. The lookup is the thing that produces a huge candidate set and then spends lots of compile-time eliminating candidates.

Your proposal seems user-friendly, and seems like it provides backwards compatibility similar to `override`, but it doesn't seem like it would help at all with the problem of `operator<<` taking forever to do overload resolution.


There are other things that might be included in the proposal:
1) requesting ADL via operator keyword at the call-site: operator swap(a, b);
2) searching "operator functions" among class members, thus allowing uniform function call syntax at least for them.
But before exploring those directions further I would like to get feedback on the main idea.

FYI, (1) seems like a non-starter unless you can solve the parsing problem.  `operator swap();` is already valid C++ syntax.
(With some fun implementation divergence there! https://godbolt.org/z/GKb756 )

HTH,
Arthur