#include <vector>
#include <iostream>

/////////////////////////////////////////////////////////////////////////////
// Data struct
/////////////////////////////////////////////////////////////////////////////

struct point { 
    point(int x, int y):x(x), y(y) {} 
    int x, y ;
} ;

/////////////////////////////////////////////////////////////////////////////
// Seperated x & y implementation
/////////////////////////////////////////////////////////////////////////////

int max_x ( std::vector<point>& v ) {
        int result = v[0].x ;
        for ( std::vector<point>::size_type i = 1; i != v.size(); ++i )
                if(v[i].x > result)
                        result = v[i].x ;
        return result ;
}

int max_y ( std::vector<point>& v ) {
        int result = v[0].y ;
        for ( std::vector<point>::size_type i = 1; i != v.size(); ++i )
                if(v[i].y > result)
                        result = v[i].y ;
        return result ;
}

/////////////////////////////////////////////////////////////////////////////
// Access function
/////////////////////////////////////////////////////////////////////////////

int& access(point& p, const int index) {
    return index == 0 ? p.x : p.y ;
}

int max ( std::vector<point>& v, const int index) {
        int result = access(v[0], index) ;
        for ( std::vector<point>::size_type i = 1; i != v.size(); ++i )
                if(access(v[i], index) > result)
                        result = access(v[i], index) ;
        return result ;
}

/////////////////////////////////////////////////////////////////////////////
// Specialized access function template
/////////////////////////////////////////////////////////////////////////////

template < int N > int& access(point& p) ;
template <> int& access<0>(point& p) { return p.x ; }
template <> int& access<1>(point& p) { return p.y ; }

template < int N >
int max ( std::vector<point>& v) {
        int result = access<N>(v[0]) ;
        for ( std::vector<point>::size_type i = 1; i != v.size(); ++i )
                if(access<N>(v[i]) > result)
                        result = access<N>(v[i]) ;
        return result ;
}

/////////////////////////////////////////////////////////////////////////////
// Pointer-to-member
/////////////////////////////////////////////////////////////////////////////

int max ( std::vector<point>& v, int point::*m )
{
    int result = v[0].*m ;
        for ( std::vector<point>::size_type i = 1; i != v.size(); ++i )
                if(v[i].*m > result)
                        result = v[i].*m ;
        return result ;
}

template < typename T >
int max ( std::vector<point>& v, T m )
{
    int result = v[0].*m ;
        for ( std::vector<point>::size_type i = 1; i != v.size(); ++i )
                if(v[i].*m > result)
                        result = v[i].*m ;
        return result ;
}

/////////////////////////////////////////////////////////////////////////////
// main
/////////////////////////////////////////////////////////////////////////////

int main()
{
    std::vector<point> v ;
    v.push_back(point(1, 9));
    v.push_back(point(2, 8));
    v.push_back(point(3, 7));
    v.push_back(point(4, 6));
    v.push_back(point(5, 5));

    // Seperated x & y implementation
    std::cout << max_x(v) << std::endl ;
    std::cout << max_y(v) << std::endl ;

    // access function
    std::cout << max(v, 0) << std::endl ;
    std::cout << max(v, 1) << std::endl ;

    // Specialized access function template
    std::cout << max<0>(v) << std::endl ;
    std::cout << max<1>(v) << std::endl ;

    // Pointer-to-member
    std::cout << max(v, &point::x) << std::endl ;
    std::cout << max(v, &point::y) << std::endl ;
}