为什么编译器无法推断出模板模板参数?

问题描述

我想编写一个函数,该函数接受具有任何类型的通用容器并进行打印。
让我们先说一下,它不适用于某些关联的容器,并专注于该问题:

template<template<typename> typename Cont,typename T>
void print(const Cont<T>& cont)
{
   for (const auto it : cont)
   {
      cout << it << " ";
   }
   cout << endl;
}

int main()
{
   vector<string> v;
   print(v);
}

错误状态:

error C2672: 'print': no matching overloaded function found    
error C3207: 'print': invalid template argument for 'Cont',class template expected

任何人都可以在这里解释为什么编译器无法推断类型吗?
即使我明确声明了print<vector<string>>(v)

解决方法

std::vector有多个类模板参数。

template<
    class T,// -----------> you have mentioned!
    class Allocator = std::allocator<T>  // -----> this didn't!
> class vector;

但是您只提供了一个。这就是没有匹配的重载编译器错误的原因。

为了解决此问题,您需要在模板模板arg中提供可变参数。

template<template<typename...> typename Cont,typename T>
//       ^^^^^^^^^^^^^^^^^^^^
void print(const Cont<T>& cont)
{
   for (const auto& it : cont) {
      std::cout << it << " ";
   }
   std::cout << std::endl;
}

See a demo


但是,您可以简单地做到这一点

template <typename Cont>
void print(const Cont& cont) 
{ 
   // ...
}

或者像标准方式一样,传递the begin and end iterator of the container to the function

#include <algorithm>  // std::copy
#include <iterator>   // std::iterator_traits

template<typename Iterator>
constexpr void print(const Iterator begin,const Iterator end) noexcept
{
   using ValueType = typename std::iterator_traits<Iterator>::value_type;
   std::copy(begin,end,std::ostream_iterator<ValueType>(std::cout," "));
   std::cout << "\n";
}

并称呼它

print(v.begin(),v.end());
,

std::vector定义为

template<
    class T,class Allocator = std::allocator<T>
> class vector;

std::vector是具有两个模板参数的类模板。不匹配 您的函数的template template参数。

更改为

template <typename Cont>
void print(const Cont& cont) 
{
    for (const auto& elem : cont) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;
}

如有必要,您可以从容器中推断出T