#include <utility>
template< typename BinaryFunc, typename First, typename... Types >
struct helper;
template< typename BinaryFunc, typename First>
struct helper<BinaryFunc, First> {
typedef decltype(std::declval<First>()) type;
};
template< typename BinaryFunc, typename First, typename Second >
struct helper<BinaryFunc, First, Second> {
typedef decltype(
std::declval<BinaryFunc>()( std::declval<First>(), std::declval<Second>() )
) type;
};
template< typename BinaryFunc, typename First, typename Second, typename... Rest >
struct helper<BinaryFunc, First, Second, Rest...> {
typedef typename helper< BinaryFunc,
typename helper<BinaryFunc, First, Second>::type,
Rest...
>::type
type;
};
template< typename BinaryFunc, typename First, typename Second >
typename helper<BinaryFunc, First, Second>::type
foldl( BinaryFunc&& func, First&& first, Second&& second ) {
return func( std::forward<First>(first), std::forward<Second>(second) );
}
template< typename BinaryFunc, typename First, typename Second, typename... Rest >
typename helper<BinaryFunc, First, Second, Rest...>::type
foldl( BinaryFunc&& func, First&& first, Second&& second, Rest&&... rest ) {
return foldl(
std::forward<BinaryFunc>(func),
func( std::forward<First>(first), std::forward<Second>(second) ),
std::forward<Rest>(rest)...
);
}
struct adder
{
template< int LHS, int RHS >
std::integral_constant<int,LHS+RHS>
operator()( std::integral_constant<int,LHS>, std::integral_constant<int,RHS> )
{
return {};
}
};
int main() {
foldl( adder(),
std::integral_constant<int,1>{},
std::integral_constant<int,2>{},
std::integral_constant<int,3>{},
std::integral_constant<int,4>{}
);
return 0;
}
I2luY2x1ZGUgPHV0aWxpdHk+Cgp0ZW1wbGF0ZTwgdHlwZW5hbWUgQmluYXJ5RnVuYywgdHlwZW5hbWUgRmlyc3QsIHR5cGVuYW1lLi4uIFR5cGVzID4Kc3RydWN0IGhlbHBlcjsKCnRlbXBsYXRlPCB0eXBlbmFtZSBCaW5hcnlGdW5jLCB0eXBlbmFtZSBGaXJzdD4Kc3RydWN0IGhlbHBlcjxCaW5hcnlGdW5jLCBGaXJzdD4gewogICAgdHlwZWRlZiBkZWNsdHlwZShzdGQ6OmRlY2x2YWw8Rmlyc3Q+KCkpIHR5cGU7Cn07Cgp0ZW1wbGF0ZTwgdHlwZW5hbWUgQmluYXJ5RnVuYywgdHlwZW5hbWUgRmlyc3QsIHR5cGVuYW1lIFNlY29uZCA+CnN0cnVjdCBoZWxwZXI8QmluYXJ5RnVuYywgRmlyc3QsIFNlY29uZD4gewogICAgdHlwZWRlZiBkZWNsdHlwZSgKICAgICAgICBzdGQ6OmRlY2x2YWw8QmluYXJ5RnVuYz4oKSggc3RkOjpkZWNsdmFsPEZpcnN0PigpLCBzdGQ6OmRlY2x2YWw8U2Vjb25kPigpICkKICAgICkgdHlwZTsKfTsKCnRlbXBsYXRlPCB0eXBlbmFtZSBCaW5hcnlGdW5jLCB0eXBlbmFtZSBGaXJzdCwgdHlwZW5hbWUgU2Vjb25kLCB0eXBlbmFtZS4uLiBSZXN0ID4Kc3RydWN0IGhlbHBlcjxCaW5hcnlGdW5jLCBGaXJzdCwgU2Vjb25kLCBSZXN0Li4uPiAgewogICAgdHlwZWRlZiB0eXBlbmFtZSBoZWxwZXI8IEJpbmFyeUZ1bmMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZW5hbWUgaGVscGVyPEJpbmFyeUZ1bmMsIEZpcnN0LCBTZWNvbmQ+Ojp0eXBlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJlc3QuLi4KICAgICAgICAgICAgICAgICAgICAgICAgICAgPjo6dHlwZQogICAgICAgICAgICAgICAgICAgICB0eXBlOwp9OwoKdGVtcGxhdGU8IHR5cGVuYW1lIEJpbmFyeUZ1bmMsIHR5cGVuYW1lIEZpcnN0LCB0eXBlbmFtZSBTZWNvbmQgPgp0eXBlbmFtZSBoZWxwZXI8QmluYXJ5RnVuYywgRmlyc3QsIFNlY29uZD46OnR5cGUKZm9sZGwoIEJpbmFyeUZ1bmMmJiBmdW5jLCBGaXJzdCYmIGZpcnN0LCBTZWNvbmQmJiBzZWNvbmQgKSB7CiAgICByZXR1cm4gZnVuYyggc3RkOjpmb3J3YXJkPEZpcnN0PihmaXJzdCksIHN0ZDo6Zm9yd2FyZDxTZWNvbmQ+KHNlY29uZCkgKTsKfQoKdGVtcGxhdGU8IHR5cGVuYW1lIEJpbmFyeUZ1bmMsIHR5cGVuYW1lIEZpcnN0LCB0eXBlbmFtZSBTZWNvbmQsIHR5cGVuYW1lLi4uIFJlc3QgPgp0eXBlbmFtZSBoZWxwZXI8QmluYXJ5RnVuYywgRmlyc3QsIFNlY29uZCwgUmVzdC4uLj46OnR5cGUKZm9sZGwoIEJpbmFyeUZ1bmMmJiBmdW5jLCBGaXJzdCYmIGZpcnN0LCBTZWNvbmQmJiBzZWNvbmQsIFJlc3QmJi4uLiByZXN0ICkgewogICByZXR1cm4gZm9sZGwoCiAgICAgIHN0ZDo6Zm9yd2FyZDxCaW5hcnlGdW5jPihmdW5jKSwKICAgICAgZnVuYyggc3RkOjpmb3J3YXJkPEZpcnN0PihmaXJzdCksIHN0ZDo6Zm9yd2FyZDxTZWNvbmQ+KHNlY29uZCkgKSwKICAgICAgc3RkOjpmb3J3YXJkPFJlc3Q+KHJlc3QpLi4uCiAgICk7Cn0KCnN0cnVjdCBhZGRlcgp7CiAgIHRlbXBsYXRlPCBpbnQgTEhTLCBpbnQgUkhTID4KICAgc3RkOjppbnRlZ3JhbF9jb25zdGFudDxpbnQsTEhTK1JIUz4KICAgb3BlcmF0b3IoKSggc3RkOjppbnRlZ3JhbF9jb25zdGFudDxpbnQsTEhTPiwgc3RkOjppbnRlZ3JhbF9jb25zdGFudDxpbnQsUkhTPiApCiAgIHsKICAgICAgcmV0dXJuIHt9OwogICB9Cn07CgppbnQgbWFpbigpIHsKICAgIGZvbGRsKCBhZGRlcigpLAogICAgICBzdGQ6OmludGVncmFsX2NvbnN0YW50PGludCwxPnt9LAogICAgICBzdGQ6OmludGVncmFsX2NvbnN0YW50PGludCwyPnt9LAogICAgICBzdGQ6OmludGVncmFsX2NvbnN0YW50PGludCwzPnt9LAogICAgICBzdGQ6OmludGVncmFsX2NvbnN0YW50PGludCw0Pnt9CiAgICApOwogICAgcmV0dXJuIDA7Cn0=