【问题标题】:Conditionally override templated class member variable有条件地覆盖模板化的类成员变量
【发布时间】:2021-09-15 12:49:19
【问题描述】:

是否可以根据模板参数覆盖类成员变量?如果是,怎么做?

大致是我的问题:我有我的数组类(它是一个动态数组,具有我需要的一些特殊功能)作为基础,如下所示:

template<class T>
class Array
{
protected:
    uint size_;
    uint capacity_;
    T *data_;    // This is our array where we store the data
...
}

现在我有了自己的 SOA 类,如下所示:

template<uint N>
class SOA : public std::conditional_t<
                N == 1,
                Array<double>,
                Array<Array<double>>>
{
protected:
    Array<double> data_[N]; /* I need it ONLY IF N > 1, else we get the data_ member from Array<T> */
...
}

N 表示我们在类中存储了多少数组。 所以基类的条件是简单地检查我们是否有 1 个组件,然后回退到一个数组,或者如果我们有更多,它是一个数组数组 -> Array

但我想做的是覆盖数组类 IF N > 1 中的 data_ 成员。由于它是固定大小,我可以简单地使用数组 data_[N],所以它可以是堆栈分配的数组而不是堆分配一个。 所以基本上我需要的是根据模板参数定义data_成员。

我的另一个想法是继承 Array&lt;T&gt; IF N==1 的形式,如果不是,则不要继承,但在这种情况下,我仍然必须有条件地定义 data_ 成员,而且我也无法做到。

我知道对于 N=1,我可以简单地使用 Array&lt;T&gt; 而不是这个类,但我希望它们是同一个类,因为如果我不必处理不同的类,这将对我的代码进行巨大的简化对于 N=1,我需要处理的只是一个 SOA&lt;N&gt; 类,仅此而已。

如果不可能,我将简单地为每个SOA&lt;N&gt; 创建一个堆栈分配数组,对于 N=1,我将简单地在其中存储一个数组。但如果 N=1 时它可以像一个简单的 Array&lt;T&gt; 一样工作,那就太好了

提前致谢!

编辑:更详细地说明为什么我希望它是一个数组。如果我有 a -> 1 分量和 b -> 3 分量,并且我想将 a 与 B 的第一个分量相乘,那么我必须将 SOA&lt;T&gt; 与 Array&lt;T&gt; 相乘。如果我将 NCMPT=1 存储在一个大小为 1 的数组中,那么我总是必须提取它的第一个也是唯一的组件,以便类匹配。或者我必须为他们定义很多运算符...

解决方案:

在我的例子中,N 是从 STYPE 类型的结构中提取的。

所以这是我最终的工作解决方案。简单的专业化是不够的,顺便说一句,这个解决方案非常明显......

因此,该类将数组保存在名为 data_ 的 C 样式数组中。

但是!如果给定的 STYPE T 正好有一个组件,那么并且只有这样才能从 Array 继承。 (SDTYPE 告诉 STYPE 的数据类型)

template<STYPE T>
class SOA
{
public:
    typedef typename SDTYPE<T>::type value_type;
private:
    Array<value_type> data_[T.NCMPT];
}

template<STYPE T>
requires(T.NCMPT == 1)
class SOA<T>
    : public Array<typename SDTYPE<T>::type>
{
}

【问题讨论】:

  • 您应该提供Minimal, Reproducible Example 以便更好地解释您的问题,否则将很难为您提供帮助。
  • 问题是我的 Array 类非常大,我无法将其缩小为大小合适但可以工作的代码。但我的主要问题是我写的。只需根据模板参数定义一个类成员。而且我做不到,所以我不能给出一个最小的工作示例......所以这不是为什么它不起作用,而是如何完成问题......
  • @Ruks 我从问题的角度删除了多余的东西。但我不能举一个更好的例子,因为我不知道是否有可能这样做..

标签: c++ templates inheritance


【解决方案1】:

如果我理解正确,你想要的是partial template specialization:

// This specialization of the class will be used when N > 1
template<uint N>
class SOA : public std::conditional_t<N == 1, Array<double>, Array<Array<double>>> {
protected:
    Array<double> data_[N];

    // ...
};

// This specialization will be used when N = 1
template <>
class SOA<1> {
    // ...
};

请记住,此功能仅限于 C++14 及更高版本。

【讨论】:

  • 天哪,这太明显了。是的,完全正确,谢谢。但更具体地说,对于我的确切问题,我必须在模板之后使用 requires(N=1),因为我没有传递 N,而是一个存储 N 的结构。
  • @simre 即使您从结构中传递 N 的值,它仍然应该工作,它只需要是一个常量值。
  • 但在这种情况下,我必须使用 requires 或 enable_if 从 N 中提取值,因为我不能仅基于 N 进行专门化,但我必须根据值确定模板是否合适在 N 里面。顺便说一句,我会测试它,我正在使用 C++20,所以这对我来说很好。我只是因为森林而没有看到树......
  • 所以我做了一些测试。我编辑了我的问题,但我必须使用专业化要求,现在它按我的预期工作。
猜你喜欢
  • 2021-11-20
  • 1970-01-01
  • 2022-07-15
  • 2017-01-16
  • 1970-01-01
  • 2017-02-19
  • 1970-01-01
  • 2016-07-22
相关资源
最近更新 更多