【问题标题】:partial specialization of function in template class模板类中函数的部分特化
【发布时间】:2012-04-18 06:37:06
【问题描述】:

我有一个表示数值数组的模板类。

我希望这个类适用于任何类型的数值(例如 int、double 等)和三种类型的容器(std::vector、std::deque 和 std::list)。

以下是针对我的具体问题的相关实现部分:

template < typename Numeric_t, typename Container = std::vector<Numeric_t> >
class Array {

  // field member
  Container m_data;

  // other stuff here
  // ...

  // random element access for std::vector and std::deque
  Numeric_t & operator[] (unsigned int index) { return m_data[index]; }

  // random element access for std::list
  Numeric_t & operator [] (unsigned int index) {
    std::list<Numeric_t> :: iterator it = m_data.begin();
    std::advance(it, index);
    return *it;
  }

}

当然,编译器不允许我重载运算符[]

我需要的是一种特定于 std::list 的 operator [] 的部分特化,但在 C++ 中也不允许部分模板函数特化。

(我知道随机元素访问对于列表来说效率不高,但这不是重点)。

理想情况下,在客户端代码中,我想像这样使用 Array 类:

Array < int, std::vector<int> > vec;
Array < int, std::list<int> >   lst;

// fill arrays here
// ...

std::cout << vec[0] << std::endl;
std::cout << lst[0] << std::endl;

经过大量研究,我无法找到可行的解决方案。

解决这个问题最优雅的方法是什么?

感谢您的帮助。

【问题讨论】:

  • 我认为您的意思是“覆盖”,而不是“重载”...但我认为您需要对整个 Array 类进行专门化,以应对 Containerlist 的情况。
  • 您是否尝试为整个班级编写专业化?如果您有不特定于模板类型的代码,您可以编写模板基类并使您的专用类从该基类继承。
  • 我们已经有一个常见问题解答问题
  • @JohannesSchaub-litb 感谢您的链接。非常适合我的问题。

标签: c++ templates operator-overloading specialization


【解决方案1】:

一个干净的解决方案是使用全类模板专业化。不同的特化可以从一个公共基类派生出来,以便共享公共代码。

编写一个类ArrayBase,其中包含所有不依赖于特定容器类型的代码,并通过使其受保护或使Array 成为朋友类来授予对容器的访问权限。

template <class Numeric_t, class Container>
class Array
  : public ArrayBase<Numeric_t, Container>
{
  // Container specific code, generic version that works for all containers.
};

template <class Numeric_t>
class Array<Numeric_t, std::vector<Numeric_t>>
  : public ArrayBase<Numeric_t, std::vector<Numeric_t>>
{
  // Optimized code for std::vector.
}

另一种方法:您还可以编写一个包含代码的静态成员函数,以访问容器的idx-th 条目并专门化该函数:

template <class Numeric_t, class Container>
class Array
{
  template <class Cont>
  static Numeric_t get(Cont const& container, unsigned int idx)
  {
    std::list<Numeric_t>::iterator it = container.begin();
    std::advance(it, idx);
    return *it;
  }

  template <>
  static Numeric_t get(std::vector<Numeric_t> const& container, unsigned int idx)
  {
    return container[idx];
  }

  public:
    Numeric_t operator[](unsigned int idx) const { return get(m_data, idx); }
};

对不起,这不起作用。我忘了你不能再次专门化静态成员函数。

另一种选择是使用 SFINAE,但它不是惯用的用法,在这种情况下我不推荐它。

【讨论】:

  • 非常感谢。解决方案 1 可能更清洁,但解决方案 2 是我现在正在寻找的。但是,我必须在函数声明前添加static 关键字,并在get 函数的第二个定义中将template&lt;&gt; 更改为template&lt;Numeric_t&gt;。另外,我想知道与原始实现相比,这种方法是否会对基于 std::vector 的数组的性能产生一些影响。
猜你喜欢
  • 1970-01-01
  • 2011-06-27
  • 2011-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多