Date: Tue, 13 Dec 2022 12:47:41 +0000
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() );
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."
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() );
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."
Received on 2022-12-13 12:47:53