Я играл с этим ответом, чтобы выяснить, как он обрабатывает функции с параметрами по умолчанию. К моему удивлению, результаты разные для бесплатных функций и operator():
template <typename F>
auto func(F f) -> decltype(f(42))
{
int a = 51;
return f(51);
}
template <typename F>
auto func(F f) -> decltype(f(42, 42))
{
int a = 0;
int b = 10;
return f(a, b);
}
int defaultFree(int a, int b = 0)
{
return a;
}
auto defaultLambda = [](int a, int b = 0)
{
return a;
};
int foo()
{
return func(defaultFree);
//return func(defaultLambda);
}
func(defaultFree) выше компилируется, пока доступны оба шаблона func. Как и ожидалось, он выбирает второй, поскольку параметры по умолчанию не считаются частью сигнатуры функции. Действительно, удаление второго шаблона func вызывает ошибку компиляции.
Однако func(defaultLambda) не скомпилируется из-за двусмысленности: оба шаблона func совпадают. Удаление одного из них делает эту версию компиляцией.
(То же самое происходит, если вы вручную записываете struct с похожим operator(), конечно. Последние gcc, clang и MSVC тоже согласны с этим.)
В чем причина того, что параметр по умолчанию рассматривается внутри неоцененного контекста SFINAE для operator() но не для свободной функции?