Ошибка "лямбда не является производным от 'std :: function' - PullRequest
4 голосов
/ 14 апреля 2019

Я пытаюсь передать лямбду в std :: function <>, определенную с помощью шаблона variadic, но похоже, что это не работает в gcc.

Есть ли причина, по которой этот код не работает на gcc 7.4.0, но работает корректно на Visual Studio 2017? И есть ли способ заставить его работать также на gcc без необходимости сначала вручную конвертировать его в std :: function <>?

#include <functional>

template<class ...TParams>
int TestFunction(std::function<void(TParams...)> )
{
    return 0;
}

void Test()
{
    auto fce = [](int /*n*/, double /*d*/) {};

    //This doesn't work with error no matching function for call to 'TestFunction<int, double>(Test()::<lambda(int, double)>&)'
    TestFunction<int, double>(fce);

    //but this works correctly
    std::function<void(int, double)> fce2 = fce;
    TestFunction<int, double>(fce2);
}

Я получаю следующую ошибку:

main.cpp: In function 'void Test()':
main.cpp:116:31: error: no matching function for call to 'TestFunction<int, double>(Test()::<lambda(int, double)>&)'
  TestFunction<int, double>(fce);
                               ^
main.cpp:106:5: note: candidate: template<class ... TParams> int TestFunction(std::function<void(TParams ...)>)
 int TestFunction(std::function<void(TParams...)> fceCallback)
     ^~~~~~~~~~~~
main.cpp:106:5: note:   template argument deduction/substitution failed:
main.cpp:116:31: note:   'Test()::<lambda(int, double)>' is not derived from 'std::function<void(TParams ...)>'
  TestFunction<int, double>(fce);
                               ^

1 Ответ

3 голосов
/ 14 апреля 2019

Пакет параметров конечного шаблона всегда оставляет место для дальнейшего вывода.Указание первых двух аргументов не мешает вам делать что-то вроде этого:

std::function<void(int, double, char)> fce3 ;
TestFunction<int, double>(fce3);

В этом случае пакет будет содержать int, double, char, потому что символ был выведен из аргумента функции.Теперь, поскольку дедукция не закончена, а лямбда не является std :: function, подстановка завершается неудачно.

Чтобы это работало, вам нужно дать знать процессу дедукции, что инстанцированная функциятребуется сейчас , прежде чем будет дан аргумент.Один из способов сделать это - взять адрес функции, например:

auto pfunc = TestFunction<int, double>;
pfunc(fce);

или

(&TestFunction<int, double>)(fce);

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...