C++ 可以用作固定大小(堆栈)和动态大小(堆)的数组封装器

C++ 可以用作固定大小(堆栈)和动态大小(堆)的数组封装器,c++,arrays,c++11,stack,heap-memory,C++,Arrays,C++11,Stack,Heap Memory,昨天,我偶然发现了一个名为Eigen的库,它提供了如下签名:- Array<float,Dynamic,1> b;//<--- dynamic = unknown at compile time Array<float,3,1> c;//<--- both row(=3) and col(=1) known at compile time 我认为它非常酷,因为它可以避免不必要的堆分配。 它在某些情况下非常合适 问题: 1个类< >中支持C++

昨天,我偶然发现了一个名为Eigen的库,它提供了如下签名:-

Array<float,Dynamic,1> b;//<--- dynamic = unknown at compile time
Array<float,3,1>       c;//<--- both row(=3) and col(=1) known at compile time
我认为它非常酷,因为它可以避免不必要的堆分配。
它在某些情况下非常合适

问题: <> 1个类< <强> >中支持C++的技术/语义是什么?p> 背后有什么想法?
我不是要完整的代码或任何片段,但我不介意

答案可以忽略关于如何实现特征阵列的所有事实。(艾根只是一个例子。)

我想要一些可靠的想法来改进我自己的阵列封装器,让它变得如此酷

我拙劣的解决方案
  • 为两个场景(动态和修复)创建字段,但在每个场景中,仅使用其中的一些字段
  • 然后,spam
    std::enable_if
    控制动态vs常量,但我认为这是反模式的

他们是部分专业化的。基本上,
数组
类模板将存储的创建委托给另一个类模板,该类模板部分专用于它们命名为
动态
的某个神奇值

以下是一个基本示例:

#include <memory>

constexpr int Dynamic = -1;

template <typename T, int N>
struct Storage
{
    Storage() : data{} {}
    T data[N];
};

template <typename T>
struct Storage<T, Dynamic>
{
    Storage(int count) : data{new T[count]} {}
    Storage() = delete;
    std::unique_ptr<T[]> data;
};


template <typename T, int N>
struct Array
{
    Array() : storage{} {}
    Array(int count) : storage{count} {}
    Storage<T, N> storage;
};


int main() {
    Array<int, 4> a1;
    //Array<int, 4> a2(10);  // Error since base Storage template has no constructor taking int.
    Array<int, Dynamic> a3(10);
    //Array<int, Dynamic> a4{};  // Error since Storage<T, Dynamic> has its default constructor deleted.
}
#包括
constexpr int Dynamic=-1;
模板
结构存储
{
存储():数据{}{}
T数据[N];
};
模板
结构存储
{
存储(整数计数):数据{new T[count]}{}
存储()=删除;
std::唯一的ptr数据;
};
模板
结构数组
{
数组():存储{}{}
数组(整数计数):存储{count}{}
储存;
};
int main(){
阵列a1;
//数组a2(10);//错误,因为基本存储模板没有接受int的构造函数。
阵列a3(10);
//数组a4{};//错误,因为存储已删除其默认构造函数。
}

基本上有两个不同的
存储
模板,一个将在
N==动态
时使用,另一个将用于任何其他值


事实上,如果你看一下,你会看到一个与我的例子相似的模式。有更多的专门化来支持多个维度和各种不同对齐的数据类型,但这是同一个概念。

它们通过部分专门化来实现。基本上,
数组
类模板将存储的创建委托给另一个类模板,该类模板部分专用于它们命名为
动态
的某个神奇值

以下是一个基本示例:

#include <memory>

constexpr int Dynamic = -1;

template <typename T, int N>
struct Storage
{
    Storage() : data{} {}
    T data[N];
};

template <typename T>
struct Storage<T, Dynamic>
{
    Storage(int count) : data{new T[count]} {}
    Storage() = delete;
    std::unique_ptr<T[]> data;
};


template <typename T, int N>
struct Array
{
    Array() : storage{} {}
    Array(int count) : storage{count} {}
    Storage<T, N> storage;
};


int main() {
    Array<int, 4> a1;
    //Array<int, 4> a2(10);  // Error since base Storage template has no constructor taking int.
    Array<int, Dynamic> a3(10);
    //Array<int, Dynamic> a4{};  // Error since Storage<T, Dynamic> has its default constructor deleted.
}
#包括
constexpr int Dynamic=-1;
模板
结构存储
{
存储():数据{}{}
T数据[N];
};
模板
结构存储
{
存储(整数计数):数据{new T[count]}{}
存储()=删除;
std::唯一的ptr数据;
};
模板
结构数组
{
数组():存储{}{}
数组(整数计数):存储{count}{}
储存;
};
int main(){
阵列a1;
//数组a2(10);//错误,因为基本存储模板没有接受int的构造函数。
阵列a3(10);
//数组a4{};//错误,因为存储已删除其默认构造函数。
}

基本上有两个不同的
存储
模板,一个将在
N==动态
时使用,另一个将用于任何其他值


事实上,如果你看一下,你会看到一个与我的例子相似的模式。有更多的专门化来支持多个维度和各种不同对齐的数据类型,但这是同一个概念。

这是一个模板类,因此您可以使用enable\u if with is\u算法来进行模板专门化。这里有一个例子:@Jerry Jeremiah这是一个非常好的链接,谢谢。这实际上可能是一个答案。它是一个模板类,所以您可以使用enable\u if with is\u算法来进行模板专门化。这里有一个例子:@Jerry Jeremiah这是一个非常好的链接,谢谢。这实际上可能是一个答案。