#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;
}
I2luY2x1ZGUgPG51bWVyaWM+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDxsaXN0PgojaW5jbHVkZSA8YXJyYXk+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPGl0ZXJhdG9yPgoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCnRlbXBsYXRlPHR5cGVuYW1lIEM+CmF1dG8gYXZnX2ltcGwoY29uc3QgQyAmIHhzLCBpbnB1dF9pdGVyYXRvcl90YWcpIHsKCXVzaW5nIFQgPSBkZWNsdHlwZSgqYmVnaW4oeHMpKTsKCWF1dG8gcyA9IGFjY3VtdWxhdGUoYmVnaW4oeHMpLCBlbmQoeHMpLCBtYWtlX3BhaXIoVHt9LCAwdSksCgkJW10oYXV0byBwLCBhdXRvIHgpIHsKCQkJcmV0dXJuIG1ha2VfcGFpcihwLmZpcnN0K3gsIHAuc2Vjb25kKzF1KTsKCQl9KTsKCXJldHVybiBzLmZpcnN0L3Muc2Vjb25kOwp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBDPgphdXRvIGF2Z19pbXBsKGNvbnN0IEMgJiB4cywgcmFuZG9tX2FjY2Vzc19pdGVyYXRvcl90YWcpIHsKCXVzaW5nIFQgPSBkZWNsdHlwZSgqYmVnaW4oeHMpKTsKCXJldHVybiBhY2N1bXVsYXRlKGJlZ2luKHhzKSwgZW5kKHhzKSwgVHt9KSAvIGRpc3RhbmNlKGJlZ2luKHhzKSwgZW5kKHhzKSk7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIEM+CmF1dG8gYXZnKGNvbnN0IEMgJiB4cykgewoJcmV0dXJuIGF2Z19pbXBsKHhzLAoJCQl0eXBlbmFtZSBpdGVyYXRvcl90cmFpdHM8ZGVjbHR5cGUoYmVnaW4oeHMpKT46Oml0ZXJhdG9yX2NhdGVnb3J5e30pOwp9CgppbnQgbWFpbigpIHsKCXZlY3RvcjxpbnQ+IHZpeyAwLCAtNSB9OwoJY291dCA8PCAidmkgYXZnOiAiIDw8IGF2Zyh2aSkgPDwgZW5kbDsKCglsaXN0PGZsb2F0PiBsZnsgMC4wZiwgLTUuNWYgfTsKCWNvdXQgPDwgImxmIGF2ZzogIiA8PCBhdmcobGYpIDw8IGVuZGw7CgoJYXJyYXk8c2hvcnQsIDI+IGFzeyAwLCAtNSB9OwoJY291dCA8PCAiYXMgYXZnOiAiIDw8IGF2ZyhhcykgPDwgZW5kbDsKCglkb3VibGUgZFtdID0geyAwLCAtNS41IH07Cgljb3V0IDw8ICJkIGF2ZzogIiA8PCBhdmcoZCkgPDwgZW5kbDsKfQo=