C++ Logo

std-proposals

Advanced search

Allow operators to have a default std::source_location argument

From: Joseph Malle <malle_at_[hidden]>
Date: Fri, 6 Mar 2020 16:22:44 -0500
This proposal supersedes my previous one
(https://lists.isocpp.org/std-proposals/2020/02/1018.php). Thanks to
Arthur O'Dwyer for his comments in that thread and pointing me towards
this simpler proposal.

It is easy to capture the std::source_location of a function's call
site using a default argument (as shown in the example in
https://en.cppreference.com/w/cpp/utility/source_location). It is
much harder to capture the caller's info if the callee is an operator
because operators cannot have default arguments[1].

    struct S {};
    void foo(S, S, std::source_location loc =
std::source_location::current()); // OK
    void operator+(S, S, std::source_location loc =
std::source_location::current()); // Error

This limitation stems from the way operators use arguments to figure
out which argument is being overloaded. My previous proposal
attempted to fix this problem by allowing any default argument on any
operator, but that led to several confusing edge cases e.g.
operator++(int) vs. operator++(int n = 0).

This proposal is to allow a single default argument on any operator as
long as it is a (possibly const and/or ref) std::source_location and
defaults to std::source_location::current().

So the following would be allowed:

    struct S {};
    void operator+(S, S, std::source_location loc =
std::source_location::current()); // should be OK
    S a, b;
    a + b; // source location is captured

A default source_location can be somewhat confusing if someone tries
to use source_location without a default argument:

struct S {
    // binary multiplication operator to multiply S and std::source_location
    void operator*(std::source_location loc);

    // unary dereference operator on S that captures a std::source_location
    void operator*(std::source_location loc = std::source_location::current());
};

I think it should be some sort of error/warning to declare both of
these (and therefore also an error to define both).

This change is backwards compatible since no existing code has default
arguments on operators. I believe it is also 'forwards compatible' in
that if C++ ever allows any default arguments on operators, then code
that uses a default source_location should be fine too.

Feedback welcome.

Joseph

[1] Much harder, but not impossible. You can force your operator's
arguments to implicitly convert via a constructor that captures the
source_location. This gets very ugly if your operator's arguments are
templated. Also, the source_location of an argument is not the same
as the location of the function. They could even be in different
files.

Received on 2020-03-06 15:25:41