【问题标题】:Removing a member based on a template parameter根据模板参数删除成员
【发布时间】:2015-03-31 15:48:33
【问题描述】:

我想设计一个带有小向量优化的向量类。它看起来像:

template <typename T, int small_size = 0>
class Vector {
private:
    T data_small_[small_size];
    T* data_;
    T* size_;
    T* capacity_;
public:
    ...
}

不幸的是,大多数时候,该类将与 small_size = 0 一起使用。有没有办法删除 data_small_ for small_size = 0 而无需进入模板专业化并重写该类的整个代码?

【问题讨论】:

  • 通常你会做一个模板特化,但不是整个 Vector,一个基类。
  • 当 small_size == 0 时,您是否使用“data_small_”?如果没有,当您使用 small_size = 0 实例化类时,编译器可能会将其作为死代码删除。
  • @James:如果 small_size = 0,则代码不使用它。但我认为编译器不会删除它,因为它会影响 sizeof(Vector).
  • @Marc:嗨,Marc。我对 C++ 没有那么丰富的经验,我唯一使用的继承是抽象类。您能否详细说明您将使用什么?

标签: c++ templates vector


【解决方案1】:

您可以在此处使用empty base optimization。您必须将Vector 更改为不直接引用data_small_。相反,编写使用SmallData 来实现所需的成员函数并处理部分特化SmallData&lt;T, 0&gt; 中的small_size = 0 情况。下面是一个例子,SmallData 实现了一个复制构造函数,operator[]Vector 使用它们而不用担心small_size

template <typename T, int small_size>
class SmallData
{
 public:
  SmallData(const SmallData& other)
  {
   for(size_t i = 0; i < small_size; i++)
     data_small_[i] = other.data_small_[i];
  }

 T& operator[](int k){return data_small_[k];} 
 protected:
  T data_small_[small_size];
};

template <typename T>
class SmallData<T, 0>
{
 public:
 T& operator[](int k){//throw some error} 
};

template <typename T, int small_size = 0>
class Vector : public SmallData<T, small_size>
{
 public:
 Vector(const Vector& other) : SmallData<T, small_size>(other)
 {
  //rest of copy ctor either here on in the member init list above
 }
 T& operator[](int k)
 {
  if(k<small_size) return SmallData<T, small_size>::operator[](k);
  else return data_[k];
 }
};

【讨论】:

  • 这个想法看起来不错。但是如何编写方法?有一个 static_if 会很好,但它在 C++ 中不存在。无论 small_size 是多少,许多方法都是相同的,但有些方法取决于它的值,例如复制构造函数。
  • @InsideLoop 让SmallData 处理所有这些怎么样?不要将data_small_ 视为TVector 中的数组。而是让SmallData 公开您需要的任何数组语义。这样,您就可以将所有 small_size=0 处理转移到 SmallData&lt;T,0&gt; 专业化中。这最终可能比在Vector 中处理它更干净。如果这还不够,我猜你会被small_size==0 上的标签调度或sfinae 困住。
  • 我还不能确定。让我们具体一点。例如,无论 small_size 的值是多少,T& operator[](int k) { return data_[k] } 都将是相同的(当 small_size > 0 的情况下有效使用小尺寸优化时,data_ 将指向 data_small_[0] )。另一方面,复制构造函数将根据 small_size 的值而有所不同。那么你在哪里声明它们呢?能给我一个代码示例吗?
  • 但是如果您使用我的建议,Vector&lt;T,0&gt; 中没有名为data_small_ 的成员。所以,相反,你会在SmallData 中有这样的东西。如果调用,主模板将具有 SmallData::operator[](int k){return data_small_[k];}SmallData&lt;T,0&gt;::operator[]throw。对于复制构造函数,你很容易因为SmallDataVector 的基础。像Vector(const Vector&amp; other) : SmallData(other) {//Copy Vector specific stuff} 这样的东西。并确保SmallData 的抄袭者良好。
  • 我明白了(并且更清楚地更新了我之前对我的评论)。当 small_size > 0 时,数据既可以存储在栈上的 data_small_ 中,也可以存储在堆上的 data_ 中。您介意在您的代码中添加 T& operator[](int k)(其代码不依赖于 small_size)和一个复制构造函数(其代码依赖于 small_size)。
猜你喜欢
  • 2012-08-20
  • 2017-09-11
  • 2012-12-31
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 2014-07-26
  • 1970-01-01
相关资源
最近更新 更多