#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>
struct A
{
double a, b, c, d;
A(double a, double b, double c, double d)
: a(a), b(b), c(c), d(d)
{}
};
template <typename F>
struct CompareBy
{
bool operator()(const typename F::argument_type& x,
const typename F::argument_type& y)
{ return f(x) < f(y); }
CompareBy(const F& f) : f(f) {}
private:
F f;
};
template <typename T, typename U>
struct Member : std::unary_function<U, T>
{
Member(T U::*ptr) : ptr(ptr) {}
const T& operator()(const U& x) { return x.*ptr; }
private:
T U::*ptr;
};
template <typename F>
struct CompareBy<F> by(const F& f) { return CompareBy<F>(f); }
template <typename T, typename U>
Member<T, U> mem_ptr(T U::*ptr) { return Member<T, U>(ptr); }
struct combination : std::unary_function<A, double>
{
combination(double x, double y) : x(x), y(y) {}
double operator()(const A& u) { return x * u.a + y * u.b; }
private:
double x, y;
};
int main()
{
std::vector<A> v;
typedef std::vector<A>::iterator Iter;
v.push_back(A(1, 2, 3, 4));
v.push_back(A(3, 1, 2, 3));
v.push_back(A(2, 2, 6, -2));
Iter i = std::max_element(v.begin(), v.end(), by(mem_ptr(&A::a)));
Iter j = std::max_element(v.begin(), v.end(), by(combination(0.2, 0.8)));
std::cout << std::distance(v.begin(), i) << std::endl; // Prints 1
std::cout << std::distance(v.begin(), j) << std::endl; // Prints 2
}