On Sun, Jun 25, 2023, 16:18 Frederick Virchanza Gotham via Std-Proposals <std-proposals@lists.isocpp.org> wrote:

On Sunday, June 25, 2023, Edward Catmur wrote:

Frederick Virchanza Gotham wrote:

then in the Release build it could become:

#define g_obj ( g_optional_obj.value() )

How? Who controls this setting? 


#define __STL_OPTIONAL_SAFETY 0
#include <optional>

If you define the above macro, then for the current translation unit, 'g_obj' isn't checked to have a value.

If you set it to 1, then it's checked and will throw std::bad_optional_access.

If you set it to 2, then it's checked and it aborts.

I think it might be permissible to have __STL_OPTIONAL_SAFETY defined differently in different translation units. So for example:

monkey.hpp:
#include <optional>
#include <sstream>
inline std::optional< std::stringstream > g_opt_ss -> g_ss;

donkey.cpp:
#define __STL_OPTIONAL_SAFETY 0
#include <iostream>
#include "monkey.hpp"
void Donkey(void) { std::cout << g_ss.str() < std::endl; }

main.cpp:
#define __STL_OPTIONAL_SAFETY 1
#include <iostream>
#include "monkey.hpp"
int main(void)
{
    std::cout << g_ss.str() < std::endl;  // will throw

    extern void Donkey(void);
    Donkey();  // will crash
}

In the above program containing 3 files, main will throw, but Donkey will crash.

Most people will probably set it in their Makefile for all translation units:

CPPFLAGS += -D__STL_OPTIONAL_SAFETY=0



> If we were to have a feature like that, it feels like it would be worth generalising
> it to expression variables and, ultimately, call by name.


I don't understand what you're saying here. Please elaborate.

You have, essentially, a variable that evaluates an expression on every access. If you allow evaluating an arbitrary expression you have expression variables, or, as function parameters, call by name.


I suppose you could call it something like an 'expression variable', although we kinda already have this if you consider writing an implicit conversion operator for a class:

class MyClass {

    operator int(void)
    {
        // We can do mad stuff in here
        return 7;
    }
};

void Func(int) {}

int main(void)
{
    MyClass obj;

    Func( obj );  // This is kinda an expression variable
}

Implicit conversion operators aren't considered in many contexts, such as reference binding to deduced type or on the left hand side of the dot operator.