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
}