Параметр шаблона 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};
}