Соответствие параметров шаблонов переменных в std::function
У меня есть следующий код:
#include <iostream>
#include <functional>
template<typename Return, typename... Params>
void func(std::function<Return(Params... )> x) {}
void f(double) {}
int main() {
//func<void, double>(f); // compile error here in the variadic case
func(std::function<void(double)>(f));
}
У меня есть 2 вопроса:
1. Я не понимаю, почему линия func<void, double>(f);
дай мне ошибку компиляции
/Users/vlad/minimal.cpp:10:5: error: no matching function for call to 'func'
func<void, double>(f); // compile error here in the variadic case
^~~~~~~~~~~~~~~~~~
/Users/vlad/minimal.cpp:5:6: note: candidate template ignored: could not match 'function<void (double, type-parameter-0-1...)>' against 'void (*)(double)'
void func(std::function<Return(Params... )> x) {}
^
1 error generated.
тогда как, если я приведу параметр f
к std::function
(как в строке без комментариев) это работает.
2. И самая загадочная проблема заключается в том, что, если я использую не вариационную версию func
(т.е. просто заменить typename...
от typename
так в действительности func
занимает std::function<Return(Params)>
в качестве параметра), то закомментированная строка в main
работает по желанию. Есть идеи почему?
1 ответ
Я не понимаю, почему линия
func<void, double>(f);
дай мне ошибку компиляции
Компилятор не знает, что вы хотите Params
быть точно double
думает, может быть, вы хотите, чтобы он выводил пакет с большим количеством элементов, таких как double, int, void*, char
или же double, double, double
или какой-то другой пакет типов, и он не знает, как вывести это из аргумента f
,
В теории могут быть и другие специализации std::function
который может быть конструктивным из f
и который позволит компилятору выводить пакет из более чем одного типа для Params
(это не может знать, что это не так, не создавая все возможные специализации std::function
и тестирование их, что неосуществимо.
тогда как, если я приведу параметр
f
кstd::function
(как в строке без комментариев) это работает.
Потому что теперь компилятор может выводить Params
правильно.
И самая загадочная проблема заключается в том, что, если я использую не вариадическую версию
func
[...] тогда прокомментированная строка в основном работает как требуется. Есть идеи почему?
Потому что теперь компилятор знает, что Params
это один тип, а не пакет из нуля или более типов, поэтому, когда вы говорите, func<void, double>
это знает Params
является double
, и не double, int, void*, char
или какой-то другой пакет параметров.
Отредактируйте в ответ на ваш комментарий, учтите это:
template<typename T, typename U, typename V>
int func(T t, U u, V v)
{ return 0; }
int i = func<int, char>(1, '2', "three");
Я дал только явный аргумент шаблона для двух параметров, так что третий еще должен быть выведен.
Если у вас есть шаблон переменной, может быть любое количество других параметров, оставшихся для вывода.