C++ Logo

std-proposals

Advanced search

[std-proposals] User defined decay operator

From: Marcin Jaczewski <marcinjaczewski86_at_[hidden]>
Date: Thu, 20 Mar 2025 17:16:30 +0100
Right now the only type that undergoes decaying is C array (aside of
refs or bit fields).
Some consider this "bad feature" but for me this is more is "bad
implementation" of "good feature".

I think that many user defined types could benefit from this functionality.

Proxy objects:
```
    std::vector<bool> ff = { false, false };
    for (auto b : ff)
    {
        b = true;
    }
    assert(ff[0] == true);
```

Expression templates:
```
auto matrix = Matrix2x2{1, 2, 3, 4}
auto mul = matrix * Vector2{3, 4};
Vector2 v = mul + Vector2{1, 1}; //UB because `mul` is expression and
dangle temporal vector
```

Recent problem discussed on this mailing list with ref types:

```
auto [a, b] = std::minmax(foo, 10);
auto c = a; // UB if `a` refer to `10`
```

Another could be a safer version of C array that is not copyable like
`std::array`
and instead of decay to pointer, it will decay to `std::span`.

And finally if someone desires to ban "Almost Always Auto" as it could
be useful for
very heavy types for unexpected copies in generic code (by setting `= delete`).

```
auto x = a; //error
auto& x = a; //ok, no decay
NestedVector x = a; //ok
auto x = NestedVector{ a }; //ok
```

Code that enable it would look like:

```
struct Foo
{
    Bar operator auto()
    {
        return Bar{};
    }
};

struct auto_ptr //pre C++11 unique_ptr
{
    //nothing change but in places where it could be used diagnostic is raised
    [[obsolete]] auto_ptr operator auto() = default;
};

struct MyArray
{
    //ban decay from temp objects like return from functions.
    std::span<int> operator auto() && = deleted;
    std::span<int> operator auto();
};

template<typename T1, typename T2>
struct MyTuple
{
    T1 t1;
    T2 t2;
    //decay propagate to members, making ref tuple safer to use if
returned form `std::minmax`
    MyTuple<std::decay_t<T1>, std::decay_t<T2>> operator auto() {
return { t1, t2 }; }
};
```

When a type has multiple `operator auto` then all versions need to
return the same type.
Additionally, the returned type need not have a decay operator (or its
`=default`).

Overall this make `auto x =` generally more safe to use and more regular.

Received on 2025-03-20 16:16:45