Проблема в том, что компилятор не может понять, что использовать для B. Чтобы определить этот тип, он хочет использовать функцию <>, которую вы передаете для f
, но вы не передаете std:: функция <> напрямую.Вы передаете что-то, что ожидаете использовать для создания функции <>.И чтобы сделать это неявное построение, ему нужно знать тип аргумента.Таким образом, у вас есть циклическая зависимость, в которой тип аргумента зависит от того, что вы передаете, но то, что передается, зависит от типа аргумента.
Вы можете разорвать эту циклическую зависимость, указав параметры шаблона,например, map_<int,int>(list, [](int x) -> char { return x + 1; });
(хотя я вижу, что функтор на самом деле возвращает символ, а не целое число, так что если здесь у вас сработало выведение типа, вы получите обратно vector<char>
, который не может быть преобразован вvector<int>
когда вы присваиваете результат transformed
)
Однако, как уже было отмечено, обычно шаблоны воспринимают функторы как простой тип шаблона:
template<typename A,typename Func>
auto map_(const std::vector<A>& orig, Func f) -> std::vector<decltype(f(A()))> {
std::vector<decltype(f(A()))> rv;
/*...*/
}
(мы используемконечный тип возвращаемого значения, потому что нам нужно использовать выражение f
в возвращаемом типе, который недоступен, если только возвращаемый тип не будет получен позднее.)
Это позволяет шаблону напрямую выводить тип функтора и избегатьлюбые преобразования типов и наилучшие возможности для оптимизации.
Также принято использовать итераторы в качестве аргументов для такого рода забавctions, в этом случае ваша функция является просто оберткой вокруг std :: transform, так что вы можете просто использовать это напрямую.Я не уверен, что есть особая ценность в специальной версии, которая имеет дело с векторами.