如何使用模板模板参数显式实例化函数

时间:2017-10-12 01:54:13

标签: c++ templates

我有一个C ++函数的形式(它有点复杂;这是MWE):

  x  y
1 0  3
2 0  3
3 0  3
4 1  2
5 0  2
6 2  0
7 0  0

我无法明确地实例化它。我尝试了大多数的排列:

template <typename T>
struct Meas {
   T time;
   T value;
};

template <typename T, template <typename U> class container>
      T func(typename container<Meas<T>>::const_iterator start,
             typename container<Meas<T>>::const_iterator end)
{
    T c = 0;
    while (start != end) {
       c += start->value;
    }
    return c;
}

X是以下之一:

template double func<double, X>(std::deque<Meas<double>>::const_iterator, 
                                std::deque<Meas<double>>::const_iterator);

但它们都没有在Xcode 9.0中编译。最常见的错误是:

  

显式实例化&#39; func&#39;不引用函数模板,变量模板,成员函数,成员类或静态数据成员

我应该如何正确地显式实例化这个函数?

2 个答案:

答案 0 :(得分:2)

std::dequetemplate<class, class>class,其中包含默认的第二个参数,而不是template<class>class。所以它没有资格。

有时template <class...> class container可以解决此问题,Xstd::deque

在您的简化示例中,container没有用处。您只需要迭代器值类型。可能这种无意义仍存在于您的真实代码中,因为想要迭代器所来自的容器不是如何设计std库的容器/迭代器设计。你不应该在乎。

使用using T=typename std::iterator_traits<Iterator>::value_type;从迭代器类型中提取T而不是你正在做的事情。

template <class It, class T=typename std::iterator_traits<It>::value_type>
T func(It start, It end)
{
  T c = 0;
  while (start != end) {
    c += start->value;
    ++start;
  }
  return c;
}

这可以推断出它的模板参数,就像99%的好模板函数一样。

然后,如果你需要实例化它:

template double func<std::deque<double>::const_iterator, double>(std::deque<double>::const_iterator, 
                            std::deque<double>::const_iterator);

可能不需要,double,我的头脑编译器不确定,我不在乎检查它。

答案 1 :(得分:2)

有两个问题,第一个问题是std::deque有两个模板参数(第二个有默认值std::allocator<T>),它与{的模板模板参数声明不匹配{1}}。您可以将func更改为template <typename U> class container或使用template <typename, typename> class container,例如template <typename...> class container,其中包含任意数量的模板参数。

第二个是func采用container<Meas<T>>::const_iterator类型的参数,它与显式实例化中的类型(即std::deque<double>::const_iterator)不匹配。

以下情况应该有效。

template <typename T, template <typename...> class container>
      T func(typename container<Meas<T>>::const_iterator start,
             typename container<Meas<T>>::const_iterator end) 
{
    ...
}

template 
double func<double, std::deque>(std::deque<Meas<double>>::const_iterator, 
                                std::deque<Meas<double>>::const_iterator);

parameter pack