#include <iostream>
#include <string>
#include <vector>
#include <typeinfo>

template<template<typename, typename> class T, typename T_T, typename T_U>
void func(T<T_T, T_U> t) {
    typename decltype(t)::iterator t_it;
    typename T<T_T, T_U>::iterator t_it2;
    std::cout << "* Passed as: "
              << typeid(T<T_T, T_U>).name() << '\n'
              << "** With element type: "
              << typeid(T_T).name() << '\n'
              << "** And allocator type: "
              << typeid(T_U).name() << '\n'
              << "** And iterator type: "
              << typeid(t_it).name() << '\n'
              << "                     (" << typeid(t_it2).name() << ")"
              << std::endl;
}

template<typename T>
void cnuf(T t) {
    std::cout << "* And as: "
              << typeid(T).name() << '\n'
              << "* With iterator type: "
              << typeid(typename T::iterator).name()
              << std::endl;
}

int main() {
    std::vector<int> vIntA;
    std::vector<int, std::allocator<std::string>> vStrA;
    
    decltype(vIntA)::iterator vII;
    decltype(vStrA)::iterator vSI;
    
    std::cout << "First vector: \n"
              << "* " << typeid(decltype(vIntA)).name() << '\n'
              << "* Allocator: "
              << typeid(decltype(vIntA)::allocator_type).name() << '\n'
              << "* Iterator: "
              << typeid(vII).name() << std::endl;
    func(vIntA);
    cnuf(vIntA);
    std::cout << std::endl;
              
    
    std::cout << "Second vector: \n"
              << "* " << typeid(decltype(vStrA)).name() << '\n'
              << "* Allocator: "
              << typeid(decltype(vStrA)::allocator_type).name() << '\n'
              << "* Iterator: "
              << typeid(vSI).name() << std::endl;
    func(vStrA);
    cnuf(vStrA);
}