C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Use optional<T> as though it were T

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Wed, 28 Jun 2023 00:47:36 +0100
I think the most efficient implementation of a "construct on demand"
object would work as follows:

        https://godbolt.org/z/dx6YTKnnj

And here it is copy-pasted:

#include <atomic> // atomic
#include <optional> // optional
#include <mutex> // once_flag, call_once, mutex, lock_guard
#include <iostream> // Just for testing: 'cout'
#include <thread> // Just for testing: 'jthread'

struct T {
     T(void) { std::cout << "Constructing. . .\n"; }
    ~T(void) { std::cout << "Destroying. . .\n" ; }
    void Speak(void) { std::cout << "Hi!\n"; }
};

std::optional<T> g_optional;

/* forward declaration of function */ T &Func_PreInit(void);

std::atomic<T &(*)(void)> g_funcptr{ &Func_PreInit };

static std::mutex g_mutex_for_optional;

T &Func_Init(void)
{
    std::cout << "> > > Func_Init\n";

    std::lock_guard mylock(g_mutex_for_optional);

    return g_optional.value();
}

std::once_flag g_flag_for_optional{};

T &Func_PreInit(void)
{
    std::cout << "> > > Func_PreInit\n";

    std::call_once(g_flag_for_optional, []()
        {
            std::lock_guard mylock(g_mutex_for_optional);
            g_optional.emplace();
        });

    g_funcptr.store( &Func_Init );

    std::lock_guard mylock(g_mutex_for_optional);
    return g_optional.value();
}

#define g_obj (g_funcptr.load()())

int main(void)
{
    g_obj.Speak();
    std::jthread mythread( [](){ g_obj.Speak(); } );
    g_obj.Speak();
}

Received on 2023-06-27 23:47:48