#include <iostream>
#include <functional>
#include <initializer_list>
template<typename Functor, typename T, size_t N>
T constexpr reduce(Functor f, T(&arr)[N]) {
typename std::remove_const<T>::type val = arr[0];
for(auto i = std::begin(arr)+1; i != std::end(arr); ++i) val = f(val, *i);
return val;
}
template<typename Functor, typename T>
T constexpr reduce(Functor f, std::initializer_list<T> il) {
T val = *il.begin();
for(auto i = il.begin()+1; i != il.end(); ++i) val = f(val, *i);
return val;
}
template<typename Functor, typename T, typename... Ts>
T constexpr reduce(Functor f, T t1, Ts... ts) {
return f(t1, reduce(f, std::initializer_list<T>({ts...})));
}
template<int value>
void print_constexpr() { std::cout << value << std::endl; }
int main() {
// run-time or compile-time
std::cout << reduce(std::plus<int>(), 1, 2, 3, 4, 5, 6, 7) << std::endl; // 28
std::cout << reduce(std::plus<int>(), {1, 2, 3, 4, 5, 6, 7}) << std::endl;// 28
const int input[3] = {1, 2, 3}; // 6
std::cout << reduce(std::plus<int>(), input) << std::endl;
// compile-time
print_constexpr< reduce(std::plus<int>(), 1, 2, 3, 4, 5, 6, 7) >(); // 28
print_constexpr< reduce(std::plus<int>(), {1, 2, 3, 4, 5, 6, 7}) >(); // 28
constexpr int input_constexpr[3] = {1, 2, 3}; // 6
print_constexpr< reduce(std::plus<int>(), input_constexpr) >(); // 6
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8ZnVuY3Rpb25hbD4KI2luY2x1ZGUgPGluaXRpYWxpemVyX2xpc3Q+Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBGdW5jdG9yLCB0eXBlbmFtZSBULCBzaXplX3QgTj4KVCBjb25zdGV4cHIgcmVkdWNlKEZ1bmN0b3IgZiwgVCgmYXJyKVtOXSkgewoJdHlwZW5hbWUgc3RkOjpyZW1vdmVfY29uc3Q8VD46OnR5cGUgdmFsID0gYXJyWzBdOwoJZm9yKGF1dG8gaSA9IHN0ZDo6YmVnaW4oYXJyKSsxOyBpICE9IHN0ZDo6ZW5kKGFycik7ICsraSkgdmFsID0gZih2YWwsICppKTsKCXJldHVybiB2YWw7CQp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBGdW5jdG9yLCB0eXBlbmFtZSBUPgpUIGNvbnN0ZXhwciByZWR1Y2UoRnVuY3RvciBmLCBzdGQ6OmluaXRpYWxpemVyX2xpc3Q8VD4gaWwpIHsKCVQgdmFsID0gKmlsLmJlZ2luKCk7Cglmb3IoYXV0byBpID0gaWwuYmVnaW4oKSsxOyBpICE9IGlsLmVuZCgpOyArK2kpIHZhbCA9IGYodmFsLCAqaSk7CglyZXR1cm4gdmFsOwp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBGdW5jdG9yLCB0eXBlbmFtZSBULCB0eXBlbmFtZS4uLiBUcz4KVCBjb25zdGV4cHIgcmVkdWNlKEZ1bmN0b3IgZiwgVCB0MSwgVHMuLi4gdHMpIHsKICByZXR1cm4gZih0MSwgcmVkdWNlKGYsIHN0ZDo6aW5pdGlhbGl6ZXJfbGlzdDxUPih7dHMuLi59KSkpOwp9Cgp0ZW1wbGF0ZTxpbnQgdmFsdWU+CnZvaWQgcHJpbnRfY29uc3RleHByKCkgeyBzdGQ6OmNvdXQgPDwgdmFsdWUgPDwgc3RkOjplbmRsOyB9CgppbnQgbWFpbigpIHsKCS8vIHJ1bi10aW1lIG9yIGNvbXBpbGUtdGltZQoJc3RkOjpjb3V0IDw8IHJlZHVjZShzdGQ6OnBsdXM8aW50PigpLCAxLCAyLCAzLCA0LCA1LCA2LCA3KSA8PCBzdGQ6OmVuZGw7ICAvLyAyOAoJc3RkOjpjb3V0IDw8IHJlZHVjZShzdGQ6OnBsdXM8aW50PigpLCB7MSwgMiwgMywgNCwgNSwgNiwgN30pIDw8IHN0ZDo6ZW5kbDsvLyAyOAoJY29uc3QgaW50IGlucHV0WzNdID0gezEsIDIsIDN9OyAgIC8vIDYKCXN0ZDo6Y291dCA8PCByZWR1Y2Uoc3RkOjpwbHVzPGludD4oKSwgaW5wdXQpIDw8IHN0ZDo6ZW5kbDsKCgkvLyBjb21waWxlLXRpbWUKCXByaW50X2NvbnN0ZXhwcjwgcmVkdWNlKHN0ZDo6cGx1czxpbnQ+KCksIDEsIDIsIDMsIDQsIDUsIDYsIDcpID4oKTsgCS8vIDI4IAoJcHJpbnRfY29uc3RleHByPCByZWR1Y2Uoc3RkOjpwbHVzPGludD4oKSwgezEsIDIsIDMsIDQsIDUsIDYsIDd9KSA+KCk7IAkvLyAyOCAKCWNvbnN0ZXhwciBpbnQgaW5wdXRfY29uc3RleHByWzNdID0gezEsIDIsIDN9OyAgIC8vIDYKCXByaW50X2NvbnN0ZXhwcjwgcmVkdWNlKHN0ZDo6cGx1czxpbnQ+KCksIGlucHV0X2NvbnN0ZXhwcikgPigpOyAvLyA2IAoKCXJldHVybiAwOwp9