Вывод из шаблона выполняется перед рассмотрением аргументов по умолчанию.Кроме того, лямбды не допускаются в неоцененных операндах.
Сначала можно назначить функцию по умолчанию для переменной.Тогда вы можете разобрать его тип.Например:
auto default_functor = [](int x){ return x > 0; };
template <typename T, typename F = decltype(default_functor)>
auto function(T x, F f = default_functor)
{
return f(x);
}
Теперь вы можете использовать функцию как обычно:
bool even(int x)
{
return x % 2 == 0;
}
struct Odd {
bool operator()(int x) const
{
return x % 2 == 1;
}
};
void g()
{
function(1); // use default functor
function(1, even); // use a free function
function(1, Odd{}); // use a function object
function(1, [](int x){ return x < 0; }); // use another lambda
}
Вам не нужно явно указывать тип.
Примечание. Согласно @ StoryTeller это может привести к нарушению ODR, если вы используете его в заголовке.В этом случае вы можете использовать именованный тип функтора:
struct Positive {
constexpr bool operator(int x) const
{
return x > 0;
}
};
inline constexpr Positive default_functor{};
template <typename T, typename F = decltype(default_functor)>
auto function(T x, F f = default_functor)
{
return f(x);
}