我正在尝试编写一个可以在可变大小的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()分配的空间,并且不希望编译器为每个可能的数组大小创建函数的副本。
我想过创建一个像数组一样工作的模板,但是它会指向现有数据而不是自己分配它,但是不想重新发明轮子。
这有可能吗?
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";
}
你真正想要的是类似于提议的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 :: 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的运算符方法。
这是因为size是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
首选STL方式:将迭代器(按值)而不是容器传递给函数。
并模板化你的功能。
您的代码将与标准算法更好地集成,并且将与std :: array或其他标准容器同等地工作。
例如:
template<class InputIterator>
void myFunc (InputIterator first, InputIterator last);
除了已经提出的建议之外,我想提出我的建议。
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};