FR: implement VariantConverter for JUCE types

VariantConverter is a useful interface for working with custom types and ValueTrees, so I’m wondering if there’s a reason why JUCE doesn’t provide implementations of VariantConverter for JUCE types.

I’ve already implemented VariantConverter specializations for every JUCE type that it seems reasonable to do so for (see here, for example) – I’d be happy to put together a pull request if there’s a chance it would be accepted.

I’ve done something like this as well: squarepine_core/VariantConverters.h at main · SquarePine/squarepine_core · GitHub

Would be nice to have it in the box already.

1 Like

I think there’s a lot could be done around juce::var to make them way more friendly to use!

For example, a juce::var_cast function - similar to std::any_cast - to wrap up a call to VariantConverter, since it can be very messy to see that in code.

template<typename ReturnType>
ReturnType var_cast (const juce::var& v)
{
    return juce::VariantConverter<ReturnType>::fromVar (v);
}
auto value = juce::VariantConverter<someNamespace::SomeClass::SomeType>::fromVar (v);
// The 'fromVar' at the end can be easy to miss, so you have to go searching
// horizontally to see if you're converting a value to a var, or a var to a value!

// vs

auto value = juce::var_cast<someNamespace::SomeClass::SomeType> (v);
// Still a long line thanks to the nested type, but it's immediately obvious this is converting a var to a value
1 Like

Everybody wrote its own (e.g. i have also a VariantConverter<juce::Colour>) ; it’s super easy.
What’s happened to those user’s implementations (with a different behaviour)?

You’d get a redefinition error if JUCE added a specialisation of VariantConverter that you’ve already implemented…

If you wanted different behavior to the JUCE converters, you’d have to put your conversions in a different namespace. Only then they wouldn’t be used by juce::CachedValue and whatever else uses them in JUCE.

AFAIK there’s no way to overwrite a template specialisation.

IMHO that’s the problem.

Not ideal, but you could potentially make your own type from the existing JUCE types, through inheritance maybe, which would then let you use custom ones on top of JUCE ones.

struct MyColour : public juce::Colour
{
};

juce::CachedValue<MyColour> myColour; // Use my custom conversions.
juce::CachedValue<juce::Colour> juceColour; // Use the built-in conversions.

Doesn’t defeat the purpose to make things easier for users?
The new/default versions of the JUCE VariantConverter shouldn’t included by default.
The user should explicitly allow them to be used.

I suppose each one’s definition could be guarded by a preprocessor def like JUCE_USE_DEFAULT_kind_VARIANT_CONVERTER, which I think should default to 1, but could allow the user to “override” certain types if they have a different implementation already

1 Like