The default parameter is not part of the function signature and is not involved in template type output. Therefore, whenever you pass from f to retry_n<> , the type f is displayed as int(int, int, int) , so the local f refers to this last type, and the default parameters are outside the process. Your only solution is to use the function that you want to test directly without inferring its type, as in the comment of @Johannes Schaub-litb, or if your compiler does not support common lambdas (C ++ 14), wrap it in a functor with a variational pattern operator()
struct functor { template<typename... T> int operator()(T&&... params) { return f(std::forward<T>(params)...); } };
and use it as
retry_n<10>(functor{}, 1, 2);
source share