//Containers
#include <array>
#include <deque>
#include <forward_list>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>

//Input/Output
#include <iostream>

//Other
#include <algorithm>
#include <bitset>
#include <chrono>
#include <complex>
#include <exception>
#include <functional>
#include <initializer_list>
#include <iterator>
#include <limits>
#include <locale>
#include <memory>
#include <new>
#include <numeric>
#include <random>
#include <ratio>
#include <regex>
#include <stdexcept>
#include <string>
#include <system_error>
#include <tuple>
#include <typeindex>
#include <typeinfo>
#include <utility>
#include <valarray>

#if 1 // Not in C++11

template <std::size_t...> struct index_sequence {};

template <std::size_t N, std::size_t... Is>
struct make_index_sequence : make_index_sequence<N - 1, N - 1, Is...> {};

template <std::size_t... Is>
struct make_index_sequence<0u, Is...> : index_sequence<Is...> {};

#endif

namespace detail
{

    template<typename T>
    void debug(const std::string& name, const T& t)
    {
        std::cout << name << ": " << t << std::endl;
    }

    template<typename T>
    void debug(const std::string& name, const std::stack<T>& a) {
        auto t = a;
        int i = 0;
        while(!t.empty()){
            std::cout << name << "[" << i << "]: " << t.top() << std::endl;
            t.pop();
            i++;
        }
    }

    template<typename T>
    void debug(const std::string& name, const std::queue<T>& a) {
        auto t = a;
        int i = 0;
        while(!t.empty()){
            std::cout << name << "[" << i << "]: " << t.front() << std::endl;
            t.pop();
            i++;
        }
    }

    template<typename K, typename V>
    void debug(const std::string& /*name*/, const std::map<K, V>& m){
        for (const auto & p : m) {
            std::cout << p.first << " => " << p.second << std::endl;
        }
    }

    template<typename T>
    void debug(const std::string& name, std::vector<T>& c) {
        std::size_t i = 0;
        for (const auto& e : c)
            std::cout << name << "[" << i++ << "]: " << e << std::endl;
    }

    template<typename T>
    void debug(const std::string& name, std::set<T>& c) {
        std::size_t i = 0;
        for (const auto& e : c)
            std::cout << name << "[" << i++ << "]: " << e << std::endl;
    }

    template<typename T>
    void debug(const std::string& name, std::list<T>& c) {
        std::size_t i = 0;
        for (const auto& e : c)
            std::cout << name << "[" << i++ << "]: " << e << std::endl;
    }

    template<typename T>
    void debug(const std::string& name, std::forward_list<T>& c) {
        std::size_t i = 0;
        for (const auto& e : c)
            std::cout << name << "[" << i++ << "]: " << e << std::endl;
    }

    template<typename T>
    void debug(const std::string& name, std::deque<T>& c) {
        std::size_t i = 0;
        for (const auto& e : c)
            std::cout << name << "[" << i++ << "]: " << e << std::endl;
    }

    template <typename Tuple, std::size_t ... Is>
    void debug(const std::vector<std::string>& names, const Tuple& t, index_sequence<Is...>)
    {
        std::initializer_list<int>{(debug(names[Is], std::get<Is>(t)), 0)...};
    }

    template<typename ... Ts>
    void dispatch(const char* namesWithComma, std::tuple<Ts...> const& args){
        std::vector<std::string> names;
        std::istringstream is(namesWithComma);
        for (std::string name; getline(is, name, ',');){
            names.push_back(name);
        }
        detail::debug(names, args, make_index_sequence<sizeof...(Ts)>());
    }

}

#define debug(...) detail::dispatch(#__VA_ARGS__, std::tie(__VA_ARGS__))

int main(){
    int a = 1;
    float b = 2;
    std::vector<int> c{3};
    std::deque<int> d{4};
    std::stack<float> e; e.push(5);
    std::queue<double> f; f.push(6);
    std::map<char,int> g{{'g', 7}};
    std::forward_list<int> h{8};
    std::set<int> i{9};
    debug(a,b,c,d,e,f,g,h,i);
    return 0;
}
