Date: Tue, 13 Dec 2022 14:51:44 +0000
On Tue, 13 Dec 2022 at 12:47, Frederick Virchanza Gotham via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> I'm currently writing a program on an x86_64 desktop computer which
> will run on MS-Windows, so there are places in my C++ code where I can
> write undefined behaviour because I know how this particular
> implementation works (i.e. I'm familiar with the compiler + CPU +
> memory layout + operating system).
>
> Just yesterday I wanted to do two things:
> (1) Show a dialog box
> (2) Start a new thread
>
> My debacle however was as follows:
> a) The constructor for the DialogBox needs the stop_token of the thread
> b) The entry point for the thread needs the address of the DialogBox
>
> So if I created the DialogBox first then I wouldn't have the
> stop_token, and if I created the thread first then I wouldn't have the
> DialogBox. It's a chicken and egg problem.
>
> So here's what I did:
>
> std::optional<Dialog_Waiting> dlg;
>
> this->worker_thread = std::jthread(
> Thread_Entry_Point,
> static_cast<Dialog_Waiting*>(static_cast<void*>(&dlg)) ); //
> yeah yeah I know I know
>
> dlg.emplace( this, this->worker_thread.get_stop_source() );
>
This is a common problem, and it doesn't make sense to look for a solution
specific to std::optional. Instead, use inheritance or composition:
struct MyDialog : Dialog_Waiting {
MyDialog(MyClass* self) : Dialog_Waiting(self, (self->worker_thread =
std::jthread(
Thread_Entry_Point,
static_cast<Dialog_Waiting*>(this))).get_stop_source())
{}
};
std::optional<MyDialog> dlg(std::in_place, this);
And then just to be doubly-sure, I wrote this after it:
>
> if ( static_cast<Dialog_Waiting*>(static_cast<void*>(&dlg)) !=
> &dlg.value() )
> {
> MsgBox("The programmer needs to edit the contents of the function,
> "
> "Dialog_Main::OnClick_SendCommands because the
> std::optional "
> "object has the wrong address.");
>
> return;
> }
>
> Would it not be better to give std::optional an extra member function
> to get the address of 'where the object would be constructed',
> something like:
>
> template<typename T>
> class optional {
> alignas(T) char unsigned buf[sizeof(T)];
>
> public:
> T * GetAddress(void) const
> {
> return static_cast<T*>(static_cast<void*>(buf + 0u));
> }
> };
>
> If we were to add this feature to C++26, then we could simply give the
> following caveat in:
> "Behaviour is undefined if you dereference the return value
> from std::optional<T>::GetAddress when *this does not contain
> a value."
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
std-proposals_at_[hidden]> wrote:
> I'm currently writing a program on an x86_64 desktop computer which
> will run on MS-Windows, so there are places in my C++ code where I can
> write undefined behaviour because I know how this particular
> implementation works (i.e. I'm familiar with the compiler + CPU +
> memory layout + operating system).
>
> Just yesterday I wanted to do two things:
> (1) Show a dialog box
> (2) Start a new thread
>
> My debacle however was as follows:
> a) The constructor for the DialogBox needs the stop_token of the thread
> b) The entry point for the thread needs the address of the DialogBox
>
> So if I created the DialogBox first then I wouldn't have the
> stop_token, and if I created the thread first then I wouldn't have the
> DialogBox. It's a chicken and egg problem.
>
> So here's what I did:
>
> std::optional<Dialog_Waiting> dlg;
>
> this->worker_thread = std::jthread(
> Thread_Entry_Point,
> static_cast<Dialog_Waiting*>(static_cast<void*>(&dlg)) ); //
> yeah yeah I know I know
>
> dlg.emplace( this, this->worker_thread.get_stop_source() );
>
This is a common problem, and it doesn't make sense to look for a solution
specific to std::optional. Instead, use inheritance or composition:
struct MyDialog : Dialog_Waiting {
MyDialog(MyClass* self) : Dialog_Waiting(self, (self->worker_thread =
std::jthread(
Thread_Entry_Point,
static_cast<Dialog_Waiting*>(this))).get_stop_source())
{}
};
std::optional<MyDialog> dlg(std::in_place, this);
And then just to be doubly-sure, I wrote this after it:
>
> if ( static_cast<Dialog_Waiting*>(static_cast<void*>(&dlg)) !=
> &dlg.value() )
> {
> MsgBox("The programmer needs to edit the contents of the function,
> "
> "Dialog_Main::OnClick_SendCommands because the
> std::optional "
> "object has the wrong address.");
>
> return;
> }
>
> Would it not be better to give std::optional an extra member function
> to get the address of 'where the object would be constructed',
> something like:
>
> template<typename T>
> class optional {
> alignas(T) char unsigned buf[sizeof(T)];
>
> public:
> T * GetAddress(void) const
> {
> return static_cast<T*>(static_cast<void*>(buf + 0u));
> }
> };
>
> If we were to add this feature to C++26, then we could simply give the
> following caveat in:
> "Behaviour is undefined if you dereference the return value
> from std::optional<T>::GetAddress when *this does not contain
> a value."
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Received on 2022-12-13 14:51:57