Can't manage to use createAndAddParameter with Xcode 8.2.1


#1

Hi !
I’m working on OS X 10.11.6 with Xcode 8.2.1, trying to adapt a plugin working in JUCE 5.3.2 to JUCE 5.4.0 or 5.4.1.
It seems that I can’t switch from the deprecated createAndAddParameter method to the new one.

This a screen dump of a compilation of the standard audio plugin template, to which I just added an “AudioProcessorValueTreeState parameters;” in the class declaration, and the following code in the constructor:


While the deprecated method compiles with a simple warning (see [1]), I get a “No matching function for call to ‘make_unique’” error ([2] and [3]).

Is this due to the version of Xcode I am using, or to something else ? What is strange is that a similar expression (line 261 of juce_AudioProcessorValueTreeState.cpp) compiles correctly. I have tried different variations, but all fail for a reason or an other. Is there something that I am missing ? Thanks for any help…


#2

What is the full compiler error?


#3

I suspect that the problem is with type deduction of the brace initialisers you’ve used. Try spelling out juce::String and juce::NormalisableRange explicitly before the opening curly braces.


#4

Hi ! Thanks for the hint, the following expression compiles correctly:

parameters.createAndAddParameter (std::make_unique<Parameter> (
                  juce::String("par2"),   // parameterID
                  juce::String("Param2"),   // parameter name
                  juce::String(""),            // parameter label
                  juce::NormalisableRange<float>(0.0f, 1.0f, 0.1f), 
                  0.0f,  // default value
                  nullptr, nullptr));

I really appreciate your help.


#5

The actual message was really just:

No matching function for call to 'make_unique'

I didn’t thought to check my parameters against those of AudioProcessorValueTreeState::Parameter. The next time I’ll try to avoid this error. Thanks to both of you !


#6

Just as a heads up, it’s enough to explicitly state the NormalisableRange parameter type, you don’t need to wrap the strings in juce::String.


#7

Yes. Actually, in the sequence of following expressions:

    using Parameter = AudioProcessorValueTreeState::Parameter;
    // [1]
    parameters.createAndAddParameter (
                  "par1",   // parameterID
                  "Param1",   // parameter name
                  {},            // parameter label
                  {0.0f, 1.0f, 0.1f}, // a NormalisableRange<float>
                  0.0f,  // default value
                  nullptr, nullptr);
    // [2]
    Parameter par ("par2",   // parameterID
                   "Param2",   // parameter name
                   {},            // parameter label
                   {0.0f, 1.0f, 0.1f}, // a NormalisableRange<float>
                   0.0f,  // default value
                   nullptr, nullptr);
    // [3]
    parameters.createAndAddParameter (std::make_unique<Parameter> (
                  "par3",   // parameterID
                  "Param3",   // parameter name
                  {},            // parameter label
                  {0.0f, 1.0f, 0.1f},
                  0.0f,  // default value
                  nullptr, nullptr));
    // [4]
    parameters.createAndAddParameter (std::make_unique<Parameter> (
                  "par4",   // parameterID
                  "Param4",   // parameter name
                  String(),            // parameter label
                  NormalisableRange<float>(0.0f, 1.0f, 0.1f),
                  0.0f,  // default value
                  nullptr, nullptr));

[1] compiles correctly, but is flagged as deprecated.

[2] with the same set of arguments compiles correctly.

[3] with the same set of arguments, signals the error “No matching function to call for ‘make_unique’”

[4] is [3] corrected, with the 2 braces expressions replaced by explicit initializations.

So, it appears that “Parameter” and “std::make_unique<Parameter>” do not accept exactly the same syntax…

This may due to the Xcode I’m using (8.2.1), or to some specific behavior of “std::make_unique”…


#8

I’m not an expert, but I imagine this is due to the fact that std::make_unique<T> is a variadic template function, meaning it takes an arbitrary number of parameters of any type. The compiler has no way of figuring out what type you’re trying to instantiate with the uniform initialization (the {...} syntax), as the template argument may be any type.
Only after type deduction, the parameters are forwarded to the constructor of T.

When invoking the constructor of Parameter directly, as you do in [2], the compiler knows that the Parameter constructor expects a NormalizableRange<float> as the fourth argument, and therefore knows how to treat the uniform initialization.

The reason why you don’t have to explicitly specify the type of the string parameters when using make_unique is that there is an implicit constructor for juce::String taking a char* parameter, therefore they are implicitly converted when calling the constructor after the type is deduced to char[x].


#9

Thanks for the clarification, I have learnt something today !