Passing std:array around

Passing std:array around

本文关键字:around array std Passing      更新时间:2023-10-16

我正在尝试编写一个函数,该函数将在可变大小的std::数组上工作,例如:

std::array a<int,5>={1,2,3,4,5};
std::array b<int,3>={6,7,8};
myFunc(a);
myFunc(b);
void myFunc(std::array &p)
{
cout << "array contains " << p.size() << "elements"; 
}

但是,除非我指定了大小,否则它不起作用,但我希望函数从数组中获取大小。我真的不想要vector使用的复制和动态分配,我想使用std::array()分配的空间,不希望编译器为每个可能大小的数组创建函数的副本。

我曾想过创建一个类似数组的模板,但它会使用一个指向现有数据的指针,而不是自己分配数据,但我不想重新发明轮子。

这有可能吗?

template<typename T, size_t N>
void myFunc(std::array<T, N> const &p) {
    cout << "array contains " << p.size() << "elements"; 
}

std::array不是类,不能像类一样使用。它是一个模板,您必须实例化该模板才能获得一个可以像类一样使用的类。

此外,大小也是数组类型的一部分。如果你想要一个容器,其中的大小不是类型的一部分,那么你可以使用类似std::vector的东西。或者,您可以编写一个适用于任何具有所需功能的对象的模板:

template<typename Container>
void myFunc(Container const &p) {
    cout << "Container contains " << p.size() << "elements"; 
}

首选STL方式:将迭代器(按值)而不是容器传递给函数。并将您的函数模板化。

您的代码将更好地与标准算法集成,并且与std::array或其他标准容器同样有效。

例如:

template<class InputIterator>
void myFunc (InputIterator first, InputIterator last);

您真正想要的是类似于建议的std::array_ref(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3334.html)它接受任何大小,只包含一个指针范围(或指针和计数,具体取决于它的实现方式),而不是每个可能的容器类型、堆分配的容器或每个调用点的迭代器对的模板膨胀。

然而,人们忘记的另一个选项是std::initializer_list,它实际上是array_ref,一个轻量级的连续同质项视图。虽然是为构造函数设计的(其中名称"initializer"最有意义),但它们也可以由泛型函数使用。请注意,传递时不会复制内容,只是一个指针范围,这意味着您不需要(也不应该)通过引用传递initializer_list。

它允许您在函数调用中直接传递一系列数字:

void myFunc(std::initializer_list<int> p)
{
    cout << "array contains " << p.size() << "elements"; 
}
myFunc({1, 2, 3, 4, 5});
myFunc({6, 7, 8});

或者通过一个中间变量:

std::initializer_list<int> a = {1, 2, 3, 4, 5};
std::initializer_list<int> b = {6, 7, 8};
auto c = {1, 2, 3, 4, 5};
auto d = {6, 7, 8};
myFunc(a);
myFunc(b);
myFunc(c);
myFunc(d);

甚至,它似乎是从固定大小的std::数组改编而来的,使用了一个构造函数重载,该重载采用了一个开始/结束对。

std::array<int, 5> e = {1, 2, 3, 4, 5};
std::array<int, 3> f = {6, 7, 8};
myFunc(std::initializer_list<int>(e.data(), e.data() + e.size()));
myFunc(std::initializer_list<int>(f.data(), f.data() + f.size()));

不过,我在cppreference.com上没有看到这个构造函数重载,在N4166中也没有。因此,这种过载可能不是标准的,只能在Dinkumware的STL(Visual Studio 2015使用)中找到。此外,数组/向量没有隐式转换,最终只能编写一个中间辅助模板函数(或者编写比简单传递两个范围更多的代码),这太糟糕了。理想情况下,std::array将支持一个运算符方法,该方法将在标准中采用initializer_list或array_ref。

这是因为大小是std::array类型的一部分。

template< 
    class T, 
    std::size_t N 
> struct array;

不同大小的数组是不同的类型。你应该使用一个模板函数并写:

template< typename T, size_t N>
void myFunc( std::array<T, N> const &p) {
    std::cout << "array contains " << p.size() << "elements"; 
}

http://en.cppreference.com/w/cpp/container/array

除了已经提出的建议之外,我还想提出我的建议。

template<size_t N>
void myFunc(std::array<int, N> const &p) {
    cout << "array contains " << N << "elements"; 
}

顺便说一下,您的变量声明需要是:

std::array<int,5> a={1,2,3,4,5};  // <int, 5> needs to move to right after array.
std::array<int,3> b={6,7,8};