Not aware of any, but you can easily write one:
template<typename T>
auto coalesce(T&& t) { return *t; }
template<typename T1, typename... Ts>
auto coalesce(T1&& t1, Ts&&... ts)
{
if (t1)
{
return *t1;
}
return coalesce(std::forward<Ts>(ts)...);
}
You can also make it an operator (e.g. in a namespace, so you don't pollute global operators) or make it a custom operator.
The above solves the problem when you pass nullable types. Upon request, here's a version that works for the case when you'd like to mix nullable and non-nullables - for non-nullables, it'll return the first non-nullable, of course. This uses C++20:
template<typename T1, typename... Ts>
auto coalesce(T1&& t1, Ts&&... ts)
{
if constexpr (requires { *t1; })
{
if constexpr (sizeof...(ts))
{
return coalesce(std::forward<Ts>(ts)...);
}
return *t1;
}
return std::forward<T1>(t1);
}
Note that even this version has the issue that you can only call it with one underlying type (as in, std::common_type<T1, Ts...>
must exist). If you'd like to be able to process multiple (potentially) unrelated underlying types, you can resort to continuation passing:
template<typename Cont, typename T1, typename... Ts>
auto coalesce(const cont& c, T1&& t1, Ts&&... ts)
{
if constexpr (requires { *t1; })
{
if constexpr (sizeof...(ts))
{
return coalesce(cont, std::forward<Ts>(ts)...);
}
return cont(*t1);
}
return cont(std::forward<T1>(t1));
}