【问题标题】:How do you explicitly instantiate a function with a template template parameter如何使用模板模板参数显式实例化函数
【发布时间】:2017-10-12 01:54:12
【问题描述】:

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

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;
}

我在显式实例化它时遇到了麻烦。我已经尝试了大多数排列:

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

其中 X 为以下之一:

std::deque
template std::deque
template std::deque<double>
std::deque<double>
template <typename U> std::deque<U>
template <typename U> std::deque

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

“func”的显式实例化不指代函数模板、变量模板、成员函数、成员类或静态数据成员

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

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    有两个问题,第一个是std::deque有两个模板参数(第二个有一个默认值std::allocator&lt;T&gt;),与func的模板模板参数声明不匹配。您可以将template &lt;typename U&gt; class container 更改为template &lt;typename, typename&gt; class container 或使用parameter pack,如template &lt;typename...&gt; class container,它允许任意数量的模板参数。

    第二个是func接受container&lt;Meas&lt;T&gt;&gt;::const_iterator类型的参数,这与显式实例化中的类型不匹配(即std::deque&lt;double&gt;::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);
    

    LIVE

    【讨论】:

      【解决方案2】:

      std::deque 是带有默认第二个参数的template&lt;class, class&gt;class,而不是template&lt;class&gt;class。所以不符合条件。

      有时template &lt;class...&gt; class container 可以解决这个问题,Xstd::deque


      在您的简化示例中,container 没有任何用处。您只需要迭代器值类型。奇怪的是,这种无意义的东西仍然存在于您的真实代码中,因为想要迭代器来自的容器并不是标准库的容器/迭代器设计的设计方式。你不应该在意。

      使用using T=typename std::iterator_traits&lt;Iterator&gt;::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 可能不需要,我的内置编译器不确定,我不想检查它。

      【讨论】:

      • ……改变有效。谢谢!使用容器的要点是迭代器值类型在编写函数时是开发环境已知的,因此它可以在您键入时进行所有成员检查和智能变量完成。此外,如果我们期望值类型(此处为 Meas)是特定的,那么允许它是任何东西似乎是一个奇怪的方案。
      • 我之前的问题中有一个错字(现已修复):实例化中 std::deque 的模板参数是错误的。这似乎引起了混乱。
      猜你喜欢
      • 2011-06-23
      • 2014-06-30
      • 1970-01-01
      • 2011-10-07
      • 2010-09-18
      • 2014-10-31
      • 1970-01-01
      • 2013-02-09
      • 2019-04-15
      相关资源
      最近更新 更多