Параметр шаблона std::function не может быть выведен

Я работаю над кодом, как следующий

#include <functional>

template <typename Type>
void foo(const std::function<void(const Type&)> & handler) {}

void goo (const int&){}

int main() {
    foo([](const int&){});
    foo(goo);
}

к сожалению, он отказывается от компиляции (clang 6.0.0 и gcc 8.1.1) из-за следующей ошибки

candidate template ignored: could not match 'function<void (const type-parameter-0-0 &)>' against '(lambda at test3.cpp:13:9)'
candidate template ignored: could not match 'function<void (const type-parameter-0-0 &)>' against '(lambda at test3.cpp:13:9)'

Можно ли как-то заставить его выводить Type правильно?

1 ответ

Решение

Вы пометили C++17, поэтому вы можете использовать std::function"S.

Вы можете попробовать что-то следующим образом

template <typename F,
          typename Type = typename decltype(std::function{std::declval<F>()})::argument_type>
void foo (F f)
 {
 }

я знаю это argument_type устарел в C++17, но вы можете заменить его простым пользовательским шаблоном.

Примером

template <typename>
struct firstArg;

template <typename R, typename A0, typename ... As>
struct firstArg<std::function<R(A0, As...)>>
 { using type = A0; };

а также foo() можно записать как

template <typename F,
          typename FUNC = decltype(std::function{std::declval<F>()}),
          typename Type = typename firstArg<FUNC>::type>
void foo (F f)
 {
 }

Таким образом, вызываемый f не является std::function но это оригинальный тип (и это может быть лучше или хуже, в зависимости от ваших точных требований); если вам это нужно в std::functionВы можете получить его внутри foo() снова использовать направляющие удержания или FUNC тип

template <typename F,
          typename FUNC = decltype(std::function{std::declval<F>()}),
          typename Type = typename firstArg<FUNC>::type>
void foo (F f)
 {
   FUNC fnc{f};
 }
Другие вопросы по тегам