Projucer crash on exporter save

Saving an exporter ends up calling Project::saveProject with an empty onCompletion. Trace:

The overload resolution of NullCheckedInvocation::invoke fails, because std::function<Signature...>&& is not a forwarding ref, just an rvalue ref. I can’t find a more elegant solution than to make identical overloads for all cv and ref qualified variants of std::function.

Thanks for reporting. I’ve pushed a fix to develop here:

1 Like

That fixes this crash, but may leave the issue open for a future one. It happens that anything that doesn’t match the exact type will go to the unchecked overload, for example

std::function<int(int)> foo;
NullCheckedInvocation::invoke (foo, 3); // a non-const lvalue
NullCheckedInvocation::invoke (std::function<int(int)>(), 5); // an rvalue

(edit) Maybe this would work? It checks anything that can be initialised with nullptr.

template <typename T>
using IsConvertibleFromNullptr = std::is_convertible<std::nullptr_t, std::remove_reference_t<T>>;

template <typename Callable, typename... Args>
std::enable_if_t<IsConvertibleFromNullptr<Callable>::value, void>
static invoke (Callable&& fn, Args&&... args)
{
    if (fn != nullptr)
        fn (std::forward<Args> (args)...);
}

template <typename Callable, typename... Args>
std::enable_if_t<! IsConvertibleFromNullptr<Callable>::value, void>
static invoke (Callable&& fn, Args&&... args)
{
    fn (std::forward<Args> (args)...);
}

Thanks, I’ve pushed a fix to develop here:

This will check for a nullptr comparison operator which is a little safer since that’s the operation we want to use (not conversion).

1 Like

Great! I didn’t know how to do that, TIL =)