Построение аргумента std :: function из лямбды - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть следующая шаблонная функция (последний компилятор C ++ включен в компиляторе - но, может быть, 17 будет достаточно).

#include <functional>

template<typename TReturn, typename ...TArgs>
void MyFunction(const std::function<TReturn(TArgs...)>& callback);

int main()
{
    MyFunction(std::function([](int){}));
    MyFunction([](int){});
}

Первый вызов компилируется, когда я явно преобразовываю его в std ::функция, но во втором случае это не так.

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

Однако во втором случае он должен (?) Также знать, что лямбда должна быть преобразована в некоторую функцию std :: function, но все еще не в состоянии это сделать.

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

Сообщение об ошибке:

ошибка C2672: «MyFunction»: не найдена соответствующая перегруженная функция

ошибка C2784: 'void MyFunction (const std :: function <_Ret (_Types ...)> &)': не удалось вывести аргумент шаблона для 'const std :: function <_Ret (_Types ...)>

примечание: см. Объявление MyFunction

То, к чему я стремлюсь, это «декоратор в стиле питона».Итак, в основном это:

template<typename TReturn, typename ...TArgs>
auto MyFunction(std::function<TReturn(TArgs...)>&& callback) -> std::function<TReturn(TArgs...)>
{
     return [callback = std::move(callback)](TArgs... args)->TReturn
     {
          return callback(std::forward<TArgs>(args)...);
    };
}

Если бы я использовал шаблон вместо std :: function, как бы я вывел пакет параметров и вернул значение?Есть ли какой-нибудь способ получить его из вызываемого через некоторые «вызываемые черты»?

1 Ответ

0 голосов
/ 13 февраля 2019

Или может быть, что для шаблонов автоматическое преобразование вообще не происходит?

Да.Неявные преобразования не будут учитываться при выводе аргумента шаблона .

Вывод типа не учитывает неявные преобразования (кроме корректировок типа, перечисленных выше): это задача разрешения перегрузки,что произойдет позже.

Это означает, что с учетом MyFunction([](int){}); неявное преобразование (из лямбды в std::function) не будет рассматриваться, тогда вычет для TReturn и TArgs завершится неудачно ипопытка вызова тоже не удалась.

В качестве временного решения вы можете

  1. Использовать явное преобразование, как показано
  2. Как Комментарий предлагается, просто используйте один параметр шаблона для функторов.например,

    template<typename F>
    auto MyFunction2(F&& callback)
    {
         return [callback = std::move(callback)](auto&&... args)
         {
              return callback(std::forward<decltype(args)>(args)...);
         };
    }
    
...