Please explain AudioProcessor::createEditorIfNeeded()

I was wondering what the meaning of the createEditorIfNeeded() function is? The name suggests it’s safe to call, but if the editor is already present, it throws an assert. Upon further inspection, the function body contains this comment:

    if (activeEditor != nullptr)
    {
        // There's already an active editor! Before calling createEditorIfNeeded(),
        // you should check whether there's already an editor using getActiveEditor().

        jassertfalse;
        return nullptr;
    }

This is somewhat confusing - the name of the function suggets benevolent nature - ‘create if not available’, and yet, if it is available, it returns nullptr and throws an assert.

That’s exactly how it used to work, but a recent commit that introduced juce_audio_processors_headless changed its behaviour:

The docs still claim, that it “returns the active editor, or if there isn’t one, it will create one.”

I agree that this API seems rather useless in its current state.

I think it’s an architectural oversight, maybe it should be changed to not cause any asserts, or renamed, if the meaning is different now?

The problem with this function is ownership. It’s not clear who should own the returned editor:

  • If the editor was newly created, then the caller of this function needs to own it and delete it later on, but
  • If the editor already exists, then it must have an owner already, and it would be a mistake for the caller to attempt to delete it.

Maybe I’m missing something and there’s a way that this function can be used safely, but I can’t see it! I expect this function to be removed in the future.

I totally agree. The fundamental issue is that a single function is trying to be both a factory and an accessor, and those have incompatible ownership semantics. There’s no return type that makes both cases safe without the caller already knowing which case they’re in.

The clean fix is just to split the two roles (keep createEditor and getActiveEditor, and remove this method).

For the getter, the idiomatic modern C++ way to express “here’s a thing you can look at but must not delete” would be something like std::optional<std::reference_wrapper<AudioProcessorEditor>>. For the factory, I’d prefer an owning return type like std::unique_ptr<AudioProcessorEditor> rather than the raw pointer that createEditor returns, but I’m guessing that will stay for backward compatibility reasons.

I really like that JUCE doesn’t look like boost. JUCE probably has the cleanest look of all C++ libraries I know, so createEditor / getActiveEditor is maybe okay.

We’ve pushed a change to deprecate createEditorIfNeeded(), since its name is misleading: