From reading the docs, it says that “If you’re using a component which may be deleted by another event that’s outside of your control, use a SafePointer instead of a normal pointer to refer to it, and you can test whether it’s null before using it to see if something has deleted it.”
So I’m just wondering, based on examples of its usage in JUCE Source, why it is sometimes tested and sometimes not?
As an example, here is some code from the JUCE AudioPluginHost, that launches the AudioSettings dialog:
auto safeThis = SafePointer<MainHostWindow> (this);
w->enterModalState (true,
ModalCallbackFunction::create
([safeThis] (int)
{
auto audioState = safeThis->deviceManager.createStateXml();
getAppProperties().getUserSettings()->setValue ("audioDeviceState", audioState.get());
getAppProperties().getUserSettings()->saveIfNeeded();
if (safeThis->graphHolder != nullptr)
if (safeThis->graphHolder->graph != nullptr)
safeThis->graphHolder->graph->graph.removeIllegalConnections();
}), true);
From my reading, the first line (in the callback) would crash if safeThis was nullptr, wouldn’t it? Then, safePointer is tested for null later on, but not those first 3 lines.
Not sure about your question, but as an implementation note, if you don’t want to pollute your local scope with the safeThis variable, you can assign it in your capture list:
I tried your suggestion on Mac - worked fine. Have you tried this on Windows? Because I just moved my projects over there, and VS2019 doesn’t like it: Code:
AlertWindow::showOkCancelBox (AlertWindow::WarningIcon,
TRANS("Deleting Last Instrument Layer..."),
TRANS("This will delete any Aux and Master Layers as well!"),
TRANS("Continue"),
TRANS("Cancel"),
&pluginArea,
ModalCallbackFunction::create
([safeThis = SafePointer<InstrumentLayer> (this)] (int result)
{
if (result == 1) // OK
safeThis->pluginArea.clear();
})
);
Error:
Severity Code Description Project File Line Suppression State
Error C2440 '<function-style-cast>': cannot convert from 'const InstrumentLayer::{ctor}::<lambda_c18e30967250f17d531ac716571d20be>::()::<lambda_d84ed578c87b0cccf7b36ad7977afe15> *' to 'juce::Component::SafePointer<InstrumentLayer>'
Message No constructor could take the source type, or constructor overload resolution was ambiguous
Error C2119 'safeThis': the type for 'auto' cannot be deduced from an empty initializer
Error C2512 'InstrumentLayer::{ctor}::<lambda_c18e30967250f17d531ac716571d20be>::()::<lambda_d84ed578c87b0cccf7b36ad7977afe15>::()::<lambda_2e4964212d86284a96943fa6b90784c0>': no appropriate default constructor available
C++ Language Standard is set to “default (C++14)” in my Projucer Projects…
To be clear, this way works just fine (declare safeThis first):
auto safeThis = SafePointer<InstrumentLayer> (this);
AlertWindow::showOkCancelBox (AlertWindow::WarningIcon,
TRANS("Deleting Last Instrument Layer..."),
TRANS("This will delete any Aux and Master Layers as well!"),
TRANS("Continue"),
TRANS("Cancel"),
&pluginArea,
ModalCallbackFunction::create
([safeThis] (int result)
{
if (result == 1) // OK
safeThis->pluginArea.clear();
})
);
Guess I’ll just have to “pollute my local scope”.
The original question, though, was "why use a safePointer if you’re not going to test for it being not a nullptr?