通用函数模板,其返回的容器的大小比输入容器的大小小一

时间:2019-05-04 17:10:54

标签: c++

我想实现一个函数,该函数接受N> = 1个元素的随机访问容器并返回另一个N-1个元素的随机访问容器。我希望该函数与std :: array,std :: vector,std :: valarray一起使用,并可以扩展到其他非标准随机访问容器。如果它可以与普通C数组一起使用,那将是一个奖励,但不是必需的。

该应用是单变量Bernstein多项式导数,其中多项式系数存储在随机访问容器中(通常很小,即N <= 10)。这是一个外观的示例:

template <class InputContainer, class OutputContainer /* deduced from InputContainer? */>
OutputContainer compute_derivative(const InputContainer &c)
{
   // Create and return an OutputContainer by iterating over elements of c
}

此外,InputContainer::value_type可以是floatdoublestd::complex<float>std::complex<double>,甚至可能是std::arraystd::vector 。这些元素代表伯恩斯坦多项式的系数,并确定多项式是标量函数,平面曲线(含2个元素的系数)还是空间曲线(含3个元素的系数)或更高阶。

是否有已知的示例可以为我提到的容器以及容器中保存的类型通用地处理此类应用程序?我只想实现一次该算法,并使它适用于容器类型和系数类型的所有可能排列,但是我意识到这不可能。

假定std::vector<double>的示例实现:

std::vector<double> compute_derivative_coefficients(const std::vector<double>& c) {
  const auto N = c.size();
  std::vector<double> c_d;  // empty
  if (N > 1) {              // 0 or 1 element vectors both return an empty vector
    c_d.reserve(N - 1)
    for (std::size_t k = 0; k < N - 1; ++k) {
      c_d[k] = (N - 1) * (c[k + 1] - c[k]);
    }
  }
  return c_d;
}

1 个答案:

答案 0 :(得分:0)

这里有几件东西要拆包。

首先。推论输出容器的类型并不像听起来那么琐碎,例如array<T,N>必须推导为类型array<T,(N-1)>,而vector<T>必须推导vector<T>(与输入类型)。因此,我相信您将不得不为所有不同于默认值的容器类型手动指定扣除规则。例如:

template <typename Container>
struct Otp {
  typedef Container Type;
};

template <typename T, ::std::size_t N>
struct Otp<::std::array<T,N>> {
  typedef ::std::array<T,(N-1)> Type;
};

以此类推。 (免责声明这是为了表明想法,我没有运行此命令,也没有考虑所有可能的要求。)

第二,该功能的实际执行。如果希望它与任何容器类型一起使用,则将以某种形式或其他方式使用迭代器对。特别是::std::begin(c)::std::end(c),因为成员函数因类型不同而异,并且C样式数组没有任何成员。

现在的麻烦是,构造vector<T>array<T,(N-1)>是两个根本不同的事情,因为数组立即初始化其成员且大小为N-1,而向量的大小为{ {1}}(和容量0)。

因此,您有理由直接使用包含在其中的内容来初始化容器。

您将需要0类型的初始化函数。不幸的是,据我所知,对于OutputContainer oc = {begin,end-1};T[]这样的list-initialised类型不存在这种操作。


因此,我想您最好的选择是区分需要初始化列表的类型,并希望所有这些类型都是默认可构造的,并立即具有它们的最终大小。然后,您可以实现通用功能的两个版本。只是默认一个初始化返回值容器,然后用内容填充它的容器。也许您可以在它们的arrayif constexpr迭代器之间的距离上远离end。第二个版本用于了解迭代器对的类型,例如begin

总而言之,这可能并非微不足道,而且有很多陷阱。我希望人们在正确实现这种通用功能的同时会学到很多关于容器的知识,但是我可以肯定的是,仅针对希望使用的类型的容器实现它会容易得多。