#include <iostream>
 
template < size_t N, typename T >
struct param_packer : param_packer<N-1,T>
{
    int value;
    
    param_packer( param_packer<N-1,T> const & other, 
                  int last )
    : param_packer<N-1,T>(other), value(last) 
    { }
    
    param_packer<N+1,T>
    operator,( T append ) const {
        return param_packer<N+1,T>( *this, append );
    }
};
 
template < typename T >
struct param_packer<0,T>
{
    param_packer<1,T>
    operator,( T first ) const {
        return param_packer<1,T>( *this, first );
    }
};
 
template < size_t I, size_t N, typename T >
T&
param_at( param_packer<N,T> & pack ) {
    return static_cast< param_packer<I+1,T>* >(&pack)->value;
}
 
param_packer<0,int> _;
 
template < size_t N >
void foo( param_packer<N, int> pack ) {
    std::cout << "N = " << N << std::endl;
    std::cout << "\t param at <0> is: " << param_at<0>( pack ) << std::endl;
    std::cout << "\t param at <N-1> is: " << param_at<N-1>( pack ) << std::endl;
}
 
int main() {
    
    foo( (_, 1, 2) );
    
}