unresolved overloaded function type
От: SergH Россия  
Дата: 02.02.22 16:30
Оценка:
Привет, простите, если простой вопрос, я тут с некоторым отставанием пытаюсь освоить с++17...

Вот такой код

template<class F>
void test(F f) {
    f(1, 2);
}

template<class T>
auto func(T a, T b) {
    return a + b;
}


int main() {

    test([](auto x, auto y) { func(x, y);}); // компилируется
    test(func);                              // не компилируется
}


gcc выдаёт

test.cpp: In function ‘int main()’:
test.cpp:15:14: error: no matching function for call to ‘test(<unresolved overloaded function type>)’
   15 |     test(func);
      |              ^
test.cpp:2:6: note: candidate: ‘template<class F> void test(F)’
    2 | void test(F f) {
      |      ^~~~
test.cpp:2:6: note:   template argument deduction/substitution failed:
test.cpp:15:14: note:   couldn’t deduce template parameter ‘F’
   15 |     test(func);
      |              ^


Если func сделать простой функцией, без шаблона, всё работает. С шаблоном только через обёртку из лямбды.

Так и должно быть? Можно как-то просто объяснить, почему?
Делай что должно, и будь что будет
Re: unresolved overloaded function type
От: reversecode google
Дата: 02.02.22 16:35
Оценка:
а как она выведет что у вас там под шаблоном?

test(func<int>);
Re[2]: unresolved overloaded function type
От: SergH Россия  
Дата: 02.02.22 16:41
Оценка:
Здравствуйте, reversecode, Вы писали:

R>а как она выведет что у вас там под шаблоном?


R>test(func<int>);


Ну аргументы-auto у лямбды его же не смущают, как-то он подходящий тип определяет...
Если явно указать, конечно, работает. Но это же не очень интересные случаи, когда получается явно и коротко указать тип.
Делай что должно, и будь что будет
Re[3]: unresolved overloaded function type
От: reversecode google
Дата: 02.02.22 16:46
Оценка: 24 (1)
я не помню как там в стандарте это правильно называется и какой там пункт
но у лямбды есть сигнатура
а у шаблона нет
поэтому сделав первый проход
компилятор не находит нужной функции
как то так

есть на ютубе у Константина Владимирова
лекции по с++
там есть подобный случай
и подробное объяснение
Re[4]: unresolved overloaded function type
От: SergH Россия  
Дата: 02.02.22 16:57
Оценка:
Здравствуйте, reversecode, Вы писали:

R>я не помню как там в стандарте это правильно называется и какой там пункт

R>но у лямбды есть сигнатура
R>а у шаблона нет
R>поэтому сделав первый проход
R>компилятор не находит нужной функции
R>как то так

Понял, то есть для лямбды есть какой-то встроенный хак, ладно.

R>есть на ютубе у Константина Владимирова

R>лекции по с++
R>там есть подобный случай
R>и подробное объяснение

О, спасибо, толковых лекций мне сильно не хватало, посмотрю.
Делай что должно, и будь что будет
Re[5]: unresolved overloaded function type
От: reversecode google
Дата: 02.02.22 17:04
Оценка:
SH>Понял, то есть для лямбды есть какой-то встроенный хак, ладно.

нет, это не хак
auto это не шаблонный тип

шаблонный тип можно вывести из каких то параметров если они есть, а увас нет на первом проходе компилятора

они могут появится только на втором проходе компилятора, но до них доходит только если сигнатура функции найдена
поэтому тут провал

или подставить
тут тоже провал,

поэтому с шаблоном в данном случае можно пройти только если сделав явную подстановку типа <int>

а auto можно сказать что уже виден на первом проходе компилятора
поэтому он схватывает лямбду
Re: depended name
От: watchmaker  
Дата: 02.02.22 17:06
Оценка: 24 (1)
Здравствуйте, SergH, Вы писали:


SH>Так и должно быть? Можно как-то просто объяснить, почему?


https://en.cppreference.com/w/cpp/language/dependent_name

SH> тут с некоторым отставанием пытаюсь освоить с++17...


У тебя опечатка в С++98

Это поведение существует и требуется с первого стандарта С++. Лямбда к нему ничего нового не добавляет.
Эквивалентный код на шаблонах (в который компилятор превращает лямбду) описывается этой первой версией языка и ведёт себя так же (компилируется или нет в двух этих вызовах).
Re: unresolved overloaded function type
От: Андрей Тарасевич Беларусь  
Дата: 02.02.22 17:16
Оценка: 148 (3) +2
Здравствуйте, SergH, Вы писали:

SH>Так и должно быть? Можно как-то просто объяснить, почему?


Шаблонная лямбда порождает нешаблонный класс с шаблонным методом `operator ()`. Ключевой момент тут в том, что тип лямбды, т.е. самого closure-объекта — не шаблонный. Таким образом при вызове функции

test([](auto x, auto y) { func(x, y);});


никаких трудностей с дедукций шаблонного параметра `F` у компилятора не возникает — он сразу определен однозначно. Дедукция `auto` для вашей лямбды будет делаться позже совсем в другом месте — в точке вызова `operator ()`, то есть в точке `f(1, 2);`, где все тоже однозначно.

Для варианта

test(func);


ситуация совсем иная — дедукция всех шаблонных аргументов (и `F` для `func` и `T` для `test`) должна быть сделана немедленно в этой точке. А это невозможно.
Best regards,
Андрей Тарасевич
Отредактировано 02.02.2022 19:16 Андрей Тарасевич . Предыдущая версия . Еще …
Отредактировано 02.02.2022 17:32 Андрей Тарасевич . Предыдущая версия .
Отредактировано 02.02.2022 17:19 Андрей Тарасевич . Предыдущая версия .
Отредактировано 02.02.2022 17:18 Андрей Тарасевич . Предыдущая версия .
Re: unresolved overloaded function type
От: Sm0ke Россия ksi
Дата: 02.02.22 18:00
Оценка:
Здравствуйте, SergH, Вы писали:

SH>Привет, простите, если простой вопрос, я тут с некоторым отставанием пытаюсь освоить с++17...


SH>Вот такой код


SH>
SH>template<class F>
SH>void test(F f) {
SH>    f(1, 2);
SH>}

SH>template<class T>
SH>auto func(T a, T b) {
SH>    return a + b;
SH>}


SH>int main() {

SH>    test([](auto x, auto y) { func(x, y);}); // компилируется
SH>    test(func);                              // не компилируется
SH>}
SH>


SH>gcc выдаёт


SH>
SH>test.cpp: In function ‘int main()’:
SH>test.cpp:15:14: error: no matching function for call to ‘test(<unresolved overloaded function type>)’
SH>   15 |     test(func);
SH>      |              ^
SH>test.cpp:2:6: note: candidate: ‘template<class F> void test(F)’
SH>    2 | void test(F f) {
SH>      |      ^~~~
SH>test.cpp:2:6: note:   template argument deduction/substitution failed:
SH>test.cpp:15:14: note:   couldn’t deduce template parameter ‘F’
SH>   15 |     test(func);
SH>      |              ^
SH>


SH>Если func сделать простой функцией, без шаблона, всё работает. С шаблоном только через обёртку из лямбды.


SH>Так и должно быть? Можно как-то просто объяснить, почему?


Параметр функции test() шаблонный, следовательно компилятор не может определить адрес какой перегрузки функции func() ты хочешь передать.
Это можно указать явно:
template<class F>
void test(F f) {
    f(1, 2);
}

template<class T>
auto func(T a, T b) {
    return a + b;
}

int main() {
    test([](auto x, auto y) { func(x, y);}); // компилируется
    test( static_cast<decltype(func(1, 2)) (*)(int, int)>(func) ); // такая лапша
}
Re[2]: unresolved overloaded function type
От: SergH Россия  
Дата: 02.02.22 19:49
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Шаблонная лямбда порождает нешаблонный класс с шаблонным методом `operator ()`. Ключевой момент тут в том, что тип лямбды, т.е. самого closure-объекта — не шаблонный.


Спасибо, это всё объясняет! Я думал, он для auto заглядывает внутрь и выясняет, с каким типом её делать, и потому удивлялся, что он не может сделать то же самое и для шаблона. О таком простом и красивом способе не подумал.
Делай что должно, и будь что будет
Re[2]: unresolved overloaded function type
От: Sm0ke Россия ksi
Дата: 02.02.22 19:58
Оценка:
Здравствуйте, reversecode, Вы писали:

R>а как она выведет что у вас там под шаблоном?


R>test(func<int>);


Таким образом не будут найдены другие более подходящие нешаблонные перегрузки функции func(), если они есть.
Re[3]: unresolved overloaded function type
От: SergH Россия  
Дата: 02.02.22 20:04
Оценка:
Здравствуйте, SergH, Вы писали:

SH>Спасибо, это всё объясняет! Я думал, он для auto заглядывает внутрь и выясняет, с каким типом её делать, и потому удивлялся, что он не может сделать то же самое и для шаблона. О таком простом и красивом способе не подумал.


О! И поэтому же работает даже вот такое вот:

#include <string>
#include <iostream>

using namespace std;

template<class F>
void test(F f) {
    cout << f(1, 2) << "\n";            // складывает как числа
    cout << f("12"s, "34"s) << "\n";    // складывает как строки
}

int main() {
    test([](auto x, auto y) { return x + y;});
}


Я не ожидал, что так можно. Какая удобная штука.
Делай что должно, и будь что будет
Re[2]: depended name
От: Андрей Тарасевич Беларусь  
Дата: 02.02.22 20:24
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>Здравствуйте, SergH, Вы писали:


SH>>Так и должно быть? Можно как-то просто объяснить, почему?


W>https://en.cppreference.com/w/cpp/language/dependent_name


O_o? Никакого отношения к теме "dependent names" все это не имеет даже отдаленно.
Best regards,
Андрей Тарасевич
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.