Date: Tue, 25 Jul 2023 10:40:15 +0200
What you basically want is a variable executing user-defined code with each access.
Do you want it only for calling member functions on it?
What happens (should happen) after
auto g2 = g_obj;
g2.f();
g2.f();
Is the user function called in the first or second line? Is it called again in the 3rd line?
In other words is this property part of the type system? Like volatile, atomic. So it is transferred with auto.
It could be like defining a variable with getter/setter methods. Regardless whether it is a member variable or a global variable.
What I do not like is that you probably would prevent any caching of that variable. There are not many use cases, for which you would not make this explicit.
Typically you have code at first access or a scoped lock around a few accesses or you are accessing hardware in a low-level way and do not want the optimizer to change anything.
For the remaining cases you probably would want to make it explicit, when the function is called.
-----Ursprüngliche Nachricht-----
Von:Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]>
Gesendet:Di 25.07.2023 00:24
Betreff:[std-proposals] Functions that don‘t need parentheses to make a call
An:std-proposals <std-proposals_at_[hidden]>;
CC:Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>;
You'll occasionally see the following inside C++ files:
MyClass &GetMyClass(void)
{
static MyClass obj;
return obj;
}
#define g_obj (GetMyClass())
Since C++11, this code uses a "once_flag" behind the scenes to make
sure that it's threadsafe.
The only problem here with using the preprocessor to define 'g_obj' is
that we can't control the scope -- we can't put 'g_obj' inside a
namespace. We also need to make sure that nobody names anything
'g_obj' anywhere.
But, what if we could remove the preprocessor from the equation by
providing a syntax for functions to take "void void" instead of
"void". So we would define the function as follows:
MyClass &g_obj(void void)
{
static MyClass obj;
return obj;
}
So now in our code wherever we write "g_obj", it's as if we had
written "g_obj()".
Then we could do stuff like:
std::optional<T> g_opt;
T &g_obj(void void)
{
if ( false == g_opt.has_value() ) std::abort();
return g_opt.value();
}
We could also apply a constraint that the function must return an
L-value reference.
If you don't like the "void void" then we could have another syntax like:
T &g_obj =
{
if ( false == g_opt.has_value() ) std::abort();
return g_opt.value();
};
Using this alternative syntax, we could even put it inside a function body:
int main(void)
{
T &g_obj =
{
if ( false == g_opt.has_value() ) std::abort();
return g_opt.value();
};
g_obj.SomeMethod();
}
P.S. Totally unrelated to this, in a couple of days I'll post a paper
on NRVO working with over a dozen compilers
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2023-07-25 08:40:17