C++ Logo

STD-PROPOSALS

Advanced search

Subject: Re: [std-proposals] Operator functions to fix ADL
From: Arthur O'Dwyer (arthur.j.odwyer_at_[hidden])
Date: 2020-10-11 10:36:06


On Sun, Oct 11, 2020 at 10:16 AM Григорий Шуренков via Std-Proposals <
std-proposals_at_[hidden]> 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



STD-PROPOSALS list run by std-proposals-owner@lists.isocpp.org

Standard Proposals Archives on Google Groups