#include<vector>
#include<iostream>
using std::size_t;
using std::cout;

// Creating a multidimensional container (e.g. `vector`, `map`)
template<template<typename...> class Container,
         typename T,  
         size_t DIMENSION>
struct MultiDimensional
{
  using internal = MultiDimensional<Container, T, DIMENSION-1>;
  using type = Container<typename internal::type>;

  template<typename... Args>
  static
  type Generate (const size_t size, Args... sizes)
  {
    return type(size, internal::Generate(sizes...));
  }
};

// Last dimension overload
template<template<typename...> class Container,
         typename T>
struct MultiDimensional<Container, T, 1>  
{
  using internal = T;
  using type = Container<T>;

  static
  type Generate (const size_t size)
  {
    return type(size);
  }
};

// Wrapper for the specific requirement of creating a multidimensional `std::vector`
template<typename T,
         typename... Args>
auto make_vector(Args... sizes)
 -> typename MultiDimensional<std::vector, T, sizeof...(sizes)>::type
{
  return MultiDimensional<std::vector, T, sizeof...(sizes)>::Generate(sizes...);
}

int main ()
{
  size_t n = 5;
  auto v3 = make_vector<int>(n+1, n*2, n*3);
  cout << "v3.size() = " << v3.size() << "\n";
  cout << "v3.back().size() = " << v3.back().size() << "\n";
  cout << "v3.back().back().size() = " << v3.back().back().size() << "\n";
}
