Как работает вывод аргумента шаблона, когда перегруженная функция используется в качестве аргумента?

Это более сложный вопрос, упомянутый в разделе Как работает разрешение перегрузки, когда аргумент является перегруженной функцией?

Ниже код компилируется без проблем:

void foo() {}
void foo(int) {}
void foo(double) {}
void foo(int, double) {}

// Uncommenting below line break compilation
//template<class T> void foo(T) {}

template<class X, class Y> void bar(void (*f)(X, Y))
{
    f(X(), Y());
}

int main()
{
    bar(foo);
}

Это не выглядит сложной задачей для вывода аргумента шаблона - есть только одна функция foo() который принимает два аргумента. Тем не менее, раскомментирование перегрузки шаблона foo() (который все еще имеет только один параметр) прерывает компиляцию без видимой причины. Сбой компиляции как с gcc 5.x/6.x, так и clang 3.9.

Может ли это быть объяснено правилами разрешения перегрузки / вывода аргументов шаблона или его следует квалифицировать как дефект в этих компиляторах?

1 ответ

Решение

Как отмечено в ответе на ваш связанный вопрос:

[temp.deduct.call]/6:когда P тип функции, указатель на тип функции или указатель на тип функции-члена:

- Если аргумент является набором перегрузок, содержащим один или несколько шаблонов функций, параметр обрабатывается как не выводимый контекст.

Так как набор перегрузки содержит шаблон функции, параметр обрабатывается как невнедренный контекст. Это приводит к сбою вывода аргумента шаблона:

[temp.deduct.type]/4: [...] Если параметр шаблона используется только в не выведенных контекстах и ​​не указан явно, вывод аргумента шаблона завершается неудачно.

И этот неудачный вывод дает вам вашу ошибку. Обратите внимание, что если вы явно указываете аргументы, код успешно компилируется:

bar<int,double>(foo);

Живая демо

Другие вопросы по тегам