Home > Net >  What is the argument type deduction rule for template of template?
What is the argument type deduction rule for template of template?

Time:01-15

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.

  • Related