A recursive_transform for std::vector with various return type
I'm afraid this is reaching the limits of my knowledge about templates in C++, but I'll try to answer it anyway as best as I can:
Use std::back_inserter() to fill the vectors
Instead of constructing a vector of a given size, just declare an empty vector, but reserve enough capacity, and then use std::back_inserter() to fill it:
std::vector&lt;decltype(recursive_transform(std::declval&lt;value_type&amp;&amp;&gt;(), f))&gt; output;
output.reserve(input.size());

std::transform(input.begin(), input.end(), std::back_inserter(output),
    [f](auto&amp; element)
    {
        return recursive_transform(element, f);
    }
);

However, if you don't use std::vector but a different container type, reserve() and/or std::back_inserter() might not be appropriate.
Determining the container type
So ideally, we don't want to declare a std::vector, but rather the outer container of type T. You can use template template parameters to deconstruct templated types:
template&lt;template&lt;class&gt; class Container, class ValueType, class Function&gt;
requires is_iterable&lt;Container&lt;ValueType&gt;&gt;
auto recursive_transform(const Container&lt;ValueType&gt; &amp;input, const Function &amp;f)
{
    // You want to be able to write this:
    using TransformedValueType = decltype(recursive_transform(*input.begin(), f));
    Container&lt;TransformedValueType&gt; output;
    ...
}

Unfortunately, that doesn't work, at least not with Clang, because a std::vector actually has two template parameters, and other containers might have more or less template parameters. So the solution to that problem is to declare ValueType as a template parameter pack:
template&lt;template&lt;class...&gt; class Container, class Function, class Ts...&gt;
requires is_iterable&lt;Container&lt;Ts...&gt;&gt;
auto recursive_transform(const Container&lt;Ts...&gt; &amp;input, const Function &amp;f)
{
    using TransformedValueType = decltype(recursive_transform(*input.begin(), f));
    Container&lt;TransformedValueType&gt; output;
    ...
}

Although of course this doesn't forward the second template parameter. Putting everything so far together:
template&lt;typename T&gt;
concept is_iterable = requires(T x)
{
    *std::begin(x);
    std::end(x);
};

template&lt;class T, class Function&gt;
auto recursive_transform(const T &amp;input, const Function &amp;f)
{
    return f(input);
}

template&lt;template&lt;class...&gt; class Container, class Function, class... Ts&gt;
requires is_iterable&lt;Container&lt;Ts...&gt;&gt;
auto recursive_transform(const Container&lt;Ts...&gt; &amp;input, const Function &amp;f)
{
    using TransformedValueType = decltype(recursive_transform(*input.begin(), f));
    Container&lt;TransformedValueType&gt; output;

    std::transform(std::begin(input), std::end(input), std::back_inserter(output),
        [&amp;](auto &amp;element)
        {
            return recursive_transform(element, f);
        }
    );

    return output;
}