传递std:数组

时间:2014-04-20 22:34:59

标签: c++ arrays c++03

我试图编写一个可以在可变大小的std :: array上工作的函数,例如:

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"; 
}

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

我考虑过创建一个像数组一样工作的模板,但会指向现有数据,而不是自己分配,但不想重新发明轮子。

这有可能吗?

5 个答案:

答案 0 :(得分:8)

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"; 
}

答案 1 :(得分:3)

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

人们忘记的另一个选择是std :: initializer_list,这是一个有效的array_ref,一个轻量级的连续同类视图。虽然用于构造函数(名称&#39; initializer&#39;最有意义),但它们也可以被泛型函数使用。请注意,传递时不会复制内容,只是指针范围,这意味着您不需要(并且不应该)通过引用传递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 :: array改编而来的,它带有一个开始/结束对。

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的运算符方法。

答案 2 :(得分:1)

这是因为大小是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

答案 3 :(得分:1)

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

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

e.g。 :

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

答案 4 :(得分:0)

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

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};