Wouldn't it make more sense to have a (new) optional with a different operator dot behavior?

n4477.pdf (open-std.org)

p0252r2.pdf (open-std.org)

This is just an other use-case why it's sad that this topic does not get the attention it deserves.

Regards, Harald

On 2023-06-25 13:53, Frederick Virchanza Gotham via Std-Proposals wrote:
Let's say you started out writing a program with a global object:

    T g_obj;

Now let's say that over 15 years, your program gets a lot bigger and
so now you want to start conserving RAM. This global object has a
constructor that allocates 100 megabytes of RAM, and so you decide to
delay its construction until it's actually needed, so you change it

    optional<T> g_obj;

Of course this would mean that you need to edit the code everywhere so
that you have "g_obj->" instead of "g_obj.", unless of course you were
to do:

    optional<T> g_optional_obj;
    T &g_obj = *g_optional_obj.operator->();

Strictly speaking this is undefined behaviour but it will work fine so
long as you make sure to 'emplace' the object before using 'g_obj'.

But what if we could standardise a way of doing this that doesn't
result in undefined behaviour? One possibility could be code that
works something like as follows:

    #include <cassert>               // cassert
    #include <optional>              // optional, bad_optional_access

    using std::optional;
    using T = int;

    optional<T> g_optional_obj;

    #define NDEBUG   // Try commenting this out

    #ifdef NDEBUG
    #   define g_obj (   g_optional_obj.has_value()            \
                       ? g_optional_obj.value()                \
                       : throw std::bad_optional_access() )
    #   define g_obj ( assert(g_optional_obj.has_value()),     \
                       g_optional_obj.value() )

    // ============================== Here comes the test code:

    #include <iostream>
    using std::cout, std::endl;

    int main(void)
        g_obj = 7;
        cout << g_obj << endl;

Try it up on GodBolt: https://godbolt.org/z/cz96bMW5j

If we were to standardise a way of getting a "T&" from an
"optional<T>&" at compile time, then the syntax could be something
like as follows:

    std::optional<T> g_optional_obj -> g_obj;

Or perhaps avoid a change to the syntax of the core language, and
split it into two lines:

    std::optional<T> g_optional_obj;
    auto g_obj = g_optional_obj.compile_time_ref();

Or another possible syntax:

    std::optional<T> g_optional_obj;
    auto g_obj = std::optional_compile_time_ref( g_optional_obj );