C++ Logo

std-proposals

Advanced search

[std-proposals] Functions that don't need parentheses to make a call

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Mon, 24 Jul 2023 23:31:18 +0100
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

Received on 2023-07-24 22:24:49