Say you wanted a generic way to flatten a vector of vectors of vectors....
in other words, a multi-dimensional vector of arbitrary depth, into a
single flat vector of values... turns out it's slightly trickier than it
sounds, but possible. Here's an implementation.

-------------------------------------------------------------------------------

#include <iostream>
#include <vector>
#include <cstdint>

template<typename>
struct is_vector : std::false_type {};

template<typename T, typename A>
struct is_vector<std::vector<T,A>> : std::true_type {};

template<typename INNER, typename OUTER>
std::vector<INNER> flatten(const std::vector<OUTER>& vec)
{
   std::vector<INNER> result;
   if constexpr(is_vector<OUTER>::value)
   {
       for (const OUTER& val: vec)
       {
           const std::vector<INNER> elems = flatten<INNER>(val);
           result.insert(result.end(), elems.begin(), elems.end());
       }
   }
   else if constexpr(std::is_same<INNER, OUTER>::value)
   {
       for (const INNER& val: vec)
       {
           result.emplace_back(val);
       }
   }
   else
   {
       static_assert(false, "impossible.");
   }
   return result;
}

int main() {
   std::vector<std::vector<std::vector<float>>> floatVals =
   {
       {{1.0, 2.2, 3.3}, {4.4, 5.5, 6.6}, {7.7, 8.8}},
       {{11.0, 12.2, 13.3}, {14.4, 15.5, 16.6}, {17.7, 18.8}},
   };

   std::vector<float> flattened = flatten<float>(floatVals);

   for (float v: flattened)
   {
       std::cout << v << ", ";
   }
   std::cout << std::endl;
}

-------------------------------------------------------------------------------

This implementation is functional, albeit rather computationally unfortunate.

Alas we can't just grab the outer vector's data() and use that as our result
because vectors aren't guaranteed to be (and usually aren't) continious in
memory.

Could also be improved upon maybe by using std::copy and/or
std::back_inserter etc etc.. but whatever, this version is simple to
understand.

It's interesting that we have to use it like:

   std::vector<float> flattened = flatten<float>(floatVals);

rather than:

   std::vector<float> flattened = flatten(floatVals);

Template deduction fails for the latter case on my compiler for some reason.
You would think that the compiler would be able to deduce the first template
argument given the type of elements on the LHS, but I suspect the problem
is that it's unable to inspect the type within the vector automatically, so
we have to help it along a bit.