std::vector<juce::Label> Error

Hi, I am trying to create a std::vector for an unknown number of juce::Labels that is selectable at runtime between 1 and 10. I keep trying to create something like the following in a basic GUI application. I’m not sure why Xcode 11.3.1 (macOS Mojave 10.14.6) is giving me the error: Call to deleted constructor of 'juce::Label'. It seems a std::vector<juce::Label> does not behave the way I would expect for a std::vector<float> to behave, for example. Any insights are appreciated! Thanks for your help.

// MainComponent.h
private:
    juce::Label temp_label;
    std::vector<juce::Label> label_vec;

// MainComponent.cpp
// MainComponent::paint()

// 'num_labels' is a size_t selected from 1 to 10 
while (label_vec.size() > num_labels) {
	label_vec.pop_back();
}

for (size_t i {0}; i < num_labels; ++i) {
    label_vec.push_back(temp_label); // ERROR: Call to deleted constructor of 'juce::Label'

    label_vec[i].setText("0.0", juce::dontSendNotification);	    
    label_vec[i].setFont(juce::Font (20.0, juce::Font::plain));
    label_vec[i].setColour(juce::Label::textColourId, juce::Colours::white);
    label_vec[i].setJustificationType(juce::Justification::centred);
    addAndMakeVisible(label_vec[i]);
}

std::vector requires elements to be movable or copyable.

juce::Label is explicitly made non-copyable by the JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR macro. It’s also implicitly non-movable since it doesn’t define a move constructor.

That macro actually makes it tricky to comply with this cpp core guidelines rule about the rule of 5.

It’d be nice if the JUCE team added move constructors for things that are using that macro - or better yet, deprecate the macro and properly follow the guideline by explicitly defining copy and move constructors.


If you want a dynamic list of components, you could use std::vector<std::unique_ptr<juce::Label>>, or juce::OwnedArray<juce::Label>.

2 Likes

I would be in favor of different macros for copy and move operations:

  • JUCE_NON_COPYABLE
  • JUCE_NON_MOVABLE
  • JUCE_DEFAULT_COPYABLE
  • JUCE_DEFAULT_MOVABLE
  • JUCE_CONSTEXPR_COPYABLE
  • JUCE_CONSTEXPR_MOVABLE

I think it is the same if you write

JUCE_DEFAULT_COPYABLE (Foo)
// or
Foo (const Foo&) = default;

It would only save typing if you create all five with one macro…

We have to remember, the =default or =delete syntax wasn’t available when those macros were written. Nowadays I find little use in adding those shortcuts…

Unless you want to allow to globally override it, but that would be nasty :wink:

3 Likes

Thank you all! I really appreciate your help!

One thing JUCE does not need is more macros :stuck_out_tongue:

3 Likes