I have three functions which use template of template:
template <template <typename...> class ContainerType, typename ItemType>
bool has_item(ContainerType<ItemType> items, ItemType target_item)
{
// ...
}
template <template <typename...> class ContainerType, typename ItemType>
ContainerType<ItemType> filter(ContainerType<ItemType> items, const std::function <bool (ItemType)>& f)
{
// ...
}
template <template <typename...> class ContainerType, typename ItemType>
bool is_vector(ContainerType<ItemType> items)
{
// ...
}
I supposed that compiler can deduce the argument types successfully, but it seems that the second one can not be deduced.
std::vector<int> v = {1, 2, 3, 4, 5};
std::cout << has_item(v, 1) << std::endl; // OK
auto less_four = [](int x) { return x < 4; };
std::vector<int> v2 = filter<std::vector, int>(v, less_four); // Can not be deduced automatically by compiler
std::cout << is_vector(v2) << std::endl; // OK
(Here is the Demo)
What is the difference between these three functions, leads to the compiler fail to deduce types automatically?
CodePudding user response:
Because for the 2nd one, template argument deduction for ItemType
fails on the 2nd function parameter; implicit conversion (from lambda to std::function
) won't be considered in template argument deduction.
You can use std::type_identity
(since C 20) to exclude the 2nd function parameter from template argument deduction. E.g.
template <template <typename...> class ContainerType, typename ItemType>
ContainerType<ItemType> filter(ContainerType<ItemType> items, const std::function <bool (std::type_identity_t<ItemType>)>& f)
{
// ...
}
You can also add another template parameter and stop using std::function
.