#include <iostream>


template <typename T, typename ...Ts>
struct Foo {
    template <typename ...Us>
    static void bar(T& oT0, T& oT1, const T& iT0, const T& iT1, Us... args) {
        std::cout << " -> Foo<...>::bar() enter [ " << oT0 << ", " << oT1 << " ]" << std::endl;
        Foo<T>::bar(oT0, oT1, iT0, iT1);
        Foo<Ts...>::bar(args...);
        std::cout << " <- Foo<...>::bar() exit [ " << oT0 << ", " << oT1 << " ]" << std::endl;
    }
};

template <typename T>
struct Foo<T> {
    static void bar(T& oT0, T& oT1, const T& iT0, const T& iT1) {
        std::cout << " -> Foo<>::bar() enter [ " << oT0 << ", " << oT1 << " ]" << std::endl;
        oT0 = iT0;
        oT1 = iT1;
        std::cout << " <- Foo<>::bar() exit [ " << oT0 << ", " << oT1 << " ]" << std::endl;
    }
};


int main() {
    int i0 = -1,
        i1 = 0;
    float f0 = -97.18f,
          f1 = 3.141592f;
    std::cout << "( "<< i0 << ", " << i1 << "; " << f0 << ", " << f1 << " ) " << std::endl;

    Foo<int, float, int>::bar(i0, i1, 0, 1, f0, f1, 18.f, -7.f, i0, i1, 4, 17);
    std::cout << "( "<< i0 << ", " << i1 << "; " << f0 << ", " << f1 << " ) " << std::endl;
    
    Foo<float>::bar(f0, f1, 18.f, -7.f);
    std::cout << "( " << f0 << ", " << f1 << " ) " << std::endl;
    
    Foo<float, int>::bar(f0, f1, 2.71f, 9000.1f, i0, i1, 4, 17);
    std::cout << "( "<< i0 << ", " << i1 << "; " << f0 << ", " << f1 << " ) " << std::endl;
    
    return 0;
}
