#include <numeric>
#include <vector>
#include <list>
#include <array>
#include <iostream>
#include <iterator>

using namespace std;

template<typename C>
auto avg_impl(const C & xs, input_iterator_tag) {
	using T = decltype(*begin(xs));
	auto s = accumulate(begin(xs), end(xs), make_pair(T{}, 0u),
		[](auto p, auto x) {
			return make_pair(p.first+x, p.second+1u);
		});
	return s.first/s.second;
}

template<typename C>
auto avg_impl(const C & xs, random_access_iterator_tag) {
	using T = decltype(*begin(xs));
	return accumulate(begin(xs), end(xs), T{}) / distance(begin(xs), end(xs));
}

template<typename C>
auto avg(const C & xs) {
	return avg_impl(xs,
			typename iterator_traits<decltype(begin(xs))>::iterator_category{});
}

int main() {
	vector<int> vi{ 0, -5 };
	cout << "vi avg: " << avg(vi) << endl;

	list<float> lf{ 0.0f, -5.5f };
	cout << "lf avg: " << avg(lf) << endl;

	array<short, 2> as{ 0, -5 };
	cout << "as avg: " << avg(as) << endl;

	double d[] = { 0, -5.5 };
	cout << "d avg: " << avg(d) << endl;
}
