Я играл с этим ответом, чтобы выяснить, как он обрабатывает функции с параметрами по умолчанию. К моему удивлению, результаты разные для бесплатных функций и 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()
но не для свободной функции?