#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;
}