C ++ не может получить параметры шаблона для функций высокого порядка - PullRequest
0 голосов
/ 20 января 2019

Когда я использую функцию шаблона, которая принимает другую функцию в качестве параметра, C ++ не может получить параметры шаблона. Очень раздражает указывать их все время. Как я могу определить следующую функцию, чтобы мне не приходилось каждый раз указывать параметры типа?

#include <functional>

template <typename S, typename T>
T apply(const S& source, const function<T (const S&)>& f) {
  return f(source);
}

template <typename S, class Functor, typename T>
T applyFun(const S& source, const Functor& f) {
  return f(source);
}

int main() {
  // Can't derive T. Why?
  apply(1, [](int x) { return x + 1; });
  // Compiles
  apply<int, int>(1, [](const int& x) { return x + 1; });
  // Can't derive T. Kind of expected.
  applyFun(1, [](int x) { return x + 1; });
}

Для меня имеет смысл, почему он не может получить параметр типа во второй функции, но не в первой (поскольку x + 1 равен int, поэтому следует вывести, что T = int).

Ответы [ 2 ]

0 голосов
/ 20 января 2019

Если вы можете использовать C ++ 17, вы можете использовать инструкции по выводу для std::function следующим образом

template <typename S, typename F,
          typename T = typename decltype( std::function{std::declval<F>()} )::result_type>
T applyFun (S const & source, F const & f)
 {  
   return f(source);
 }

, но, как указал Олив, для вашей примерной функции нет необходимости в T, потому что вы можете использовать auto (из C ++ 14; auto ... -> decltype(f(source)) в C ++ 11).

- EDIT -

Оператор скажет

Хорошая особенность этого решения в том, что я могу использовать T внутри функции (например, если я хочу реализовать vector_map).

Вы можете обнаружить и использоватьT, также внутри функции, с использованием using

Что-то вроде

template <typename S, typename F>
auto applyFun (S const & source, F const & f)
 {  
   using T = typename decltype( std::function{f} )::result_type;

   return f(source);
 }

или проще: using T = decltype( f(source) );.


ОП такжеобратите внимание, что

Недостатком является то, что по какой-то причине теперь я не могу написать [] (const auto& x) { ... } в вызове функции.

Правильно.Поскольку std::function типы шаблонов не могут быть выведены из generic-lambda.

Но, учитывая тот факт, что вы знаете тип аргумента, вы можете использовать decltype() снова

template <typename S, typename F,
          typename T = decltype(std::declval<F const>()(std::declval<S const>()))>
T applyFun (S const & source, F const & f)
 { return f(source); }

Это решение должно работать также для C ++ 14 и C ++ 11.

0 голосов
/ 20 января 2019

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

Но в этом случае нет необходимости указывать тип возврата.Возвратный тип вычета может сделать работу:

template <typename S, class Functor>
auto applyFun(const S& source, const Functor& f) {
  return f(source);
  }
...