[英]Passing unknown size std::Array in a function with template. How can I correct this code?
I wrote this code using 2d Vector and Array.我使用二维向量和数组编写了这段代码。 But I wanted to use
std::array
this time and my code did not work because this was the first time I use std::array
and template.但是这次我想使用
std::array
并且我的代码不起作用,因为这是我第一次使用std::array
和模板。
It gave me for this line:它给了我这一行:
array<array<int, sizeY>, sizeX> arr;
this error:这个错误:
Error C2971
std::array
: template parameter_Size
:sizeY,sizeX
: a variable with non-static storage duration cannot be used as a non-type argument错误 C2971
std::array
:模板参数_Size
:sizeY,sizeX
:具有非静态存储持续时间的变量不能用作非类型参数
#include <iostream>
#include <array>
using namespace std;
template <size_t Y, size_t X>
bool IsMagicSquare(array<array<int, Y>, X>& ar)
{
int x = ar.size();
int y = ar[0].size();
if (x == y)
{
int ver[x] = { };
int hor[y] = { };
int cross0 = 0;
int cross1 = 0;
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
hor[i] += ar[i][j];
ver[j] += ar[i][j];
if (i == j)
cross0 += ar[i][j];
if (i + j == x - 1)
cross1 += ar[i][j];
}
}
if (cross0 != cross1)
return false;
else
{
for (int i = 0; i < x; i++)
if ((cross0 != ver[i]) || (cross1 != hor[i]))
return false;
}
}
else
return false;
return true;
}
int main()
{
int sizeX, sizeY;
cout << "Size of Matrix:";
cin >> sizeX >> sizeY;
**array<array<int, sizeY>, sizeX> arr;**
cout << "Elements of the Matrix:";
for (int i = 0; i < sizeX; i++)
for (int j = 0; j < sizeY; j++)
cin >> arr[i][j];
if (IsMagicSquare(arr))
{
for (int i = 0; i < sizeX; i++)
{
cout << "\n";
for (int j = 0; j < sizeY; j++)
cout << arr[i][j];
}
}
else
cout << "Matrix is not magical square!";
return 0;
}
The size of an array (or template arguments in general) has to be known at compile-time, so there is no way to use the runtime values sizeX
, sizeY
as size (template argument) for an array.必须在编译时知道数组(或一般模板参数)的大小,因此无法使用运行
sizeX
、 sizeY
作为数组的大小(模板参数)。
You have to use a variable-length container like std::vector
instead.您必须改用像
std::vector
这样的可变长度容器。
For reference, here's how you can get a std::array
with a size which is decided at runtime:作为参考,您可以通过以下方式获取大小由运行时决定的
std::array
:
#include <array>
#include <cstddef>
#include <iostream>
#include <memory>
template<typename T>
struct DynArray {
virtual std::size_t size() const = 0;
virtual T * data() = 0;
virtual ~DynArray() {}
};
template<typename T, std::size_t Size>
struct DynArrayImpl : public DynArray<T> {
std::array<T, Size> array;
std::size_t size() const override {
return array.size();
}
T * data() override {
return array.data();
}
};
template<typename T, std::size_t Size>
struct DynArrayFactory {
static DynArray<T> * allocate(std::size_t const size) {
if (size > Size) {
// ERROR
return nullptr;
}
if (size == Size) {
return new DynArrayImpl<T, Size>();
}
return DynArrayFactory<T, Size - 1>::allocate(size);
}
};
template<typename T>
struct DynArrayFactory<T, 0> {
static DynArray<T> * allocate(std::size_t const size) {
if (size > 0) {
return nullptr;
}
return new DynArrayImpl<T, 0>();
}
};
int main() {
std::size_t size;
std::cin >> size;
std::unique_ptr<DynArray<int>> array{DynArrayFactory<int, 100>::allocate(size)};
std::cout << array->size() << std::endl;
}
This requires a maximum size (100 in this case) to be specified at compile time and is a really convoluted way of doing things;这需要在编译时指定最大大小(在这种情况下为 100),这是一种非常复杂的做事方式; thus not recommended .
因此不推荐。
Accessing the std::array
is nearly impossible though, unless with similar templated code which then generates code for each possible size (see below).不过,访问
std::array
几乎是不可能的,除非使用类似的模板化代码,然后为每个可能的大小生成代码(见下文)。 This will generate a lot of code.这将生成大量代码。 One can easily access the contents of the array however, as seen in the example above.
但是,如上例所示,可以轻松访问数组的内容。 But really: use
std::vector
.但实际上:使用
std::vector
。
"similar templated code": “类似的模板代码”:
template<std::size_t Size>
struct FillWithNumbers {
static void run(std::array<int, Size> & array) {
int n = 0;
std::generate(begin(array), end(array), [&n](){ return n++; });
}
};
template<typename T, std::size_t Size>
struct DynArrayApply {
template<template<std::size_t S> class Fn>
static void apply(DynArray<T> & array) {
if (array.size() > Size) {
// ERROR
}
if (array.size() == Size) {
DynArrayImpl<T, Size> & real = dynamic_cast<DynArrayImpl<T, Size> &>(array);
Fn<Size>::run(real.array);
}
else {
DynArrayApply<T, Size - 1>::template apply<Fn>(array);
}
}
};
template<typename T>
struct DynArrayApply<T,0> {
template<template<std::size_t S> class Fn>
static void apply(DynArray<T> & array) {
if (array.size() > 0) {
// ERROR
}
DynArrayImpl<T, 0> & real = dynamic_cast<DynArrayImpl<T, 0> &>(array);
Fn<0>::run(real.array);
}
};
int main() {
std::size_t size;
std::cin >> size;
std::unique_ptr<DynArray<int>> array{DynArrayFactory<int, 100>::allocate(size)};
DynArrayApply<int, 100>::apply<FillWithNumbers>(*array);
std::cout << array->size() << std::endl;
std::cout << array->data()[array->size() / 2] << std::endl;
}
I wrote this code using 2d Vector and Array.
我使用二维向量和数组编写了这段代码。
That is appropriate, as you do not know the size of the matrix until run time.这是合适的,因为您直到运行时才知道矩阵的大小。
But I wanted to use
std::array
this time [...]但这次我想使用
std::array
[...]
Well, that's a problem because the size of a std::array
must be known at compile time.嗯,这是一个问题,因为在编译时必须知道
std::array
的大小。 Moving away from C-style arrays is a recommended move, but you have to know where to go.远离 C 风格的数组是推荐的做法,但您必须知道该去哪里。 Use the correct tool for the job at hand.
为手头的工作使用正确的工具。
Fixed-size arrays: For arrays whose size is known by the compiler, a std::array
is a reasonable replacement.固定大小的数组:对于编译器已知大小的数组,
std::array
是一个合理的替代品。 In fact, the std::array
is probably nothing more than the C-style array with a different interface.实际上,
std::array
可能只不过是具有不同接口的 C 样式数组。
Variable-size arrays: For arrays whose size is not known until run time, a std::vector
is a reasonable replacement.可变大小的数组:对于直到运行时才知道大小的数组,
std::vector
是一个合理的替代品。 Even though the name does not say "array", it is an array.即使名称没有说“数组”,它也是一个数组。 It is a bit more complex than
std::array
, but that is because it supports sizes not known at compile time.它比
std::array
复杂一些,但这是因为它支持编译时未知的大小。
This distinction tends to be better-known by those not using gcc, as that compiler has an extension that supports declaring variable-size C-style arrays using the same syntax as declaring fixed-size C-style arrays.那些不使用 gcc 的人往往更清楚这种区别,因为该编译器有一个扩展,支持使用与声明固定大小的 C 样式数组相同的语法来声明可变大小的 C 样式数组。 It is standard C++ to declare an array along the lines of
int col[10]
.按照
int col[10]
的行声明数组是标准的 C++。 However, it is not standard C++ to declare an array along the lines of int col[sizeY]
, where sizeY
has a value supplied at run time.但是,按照
int col[sizeY]
行声明数组并不是标准的 C++,其中sizeY
具有在运行时提供的值。 The latter syntax is supported by gcc as an extension, and some people use it without realizing it is an extension (ported from gcc's C support). gcc 支持后一种语法作为扩展,有些人使用它而没有意识到它是一个扩展(从 gcc 的 C 支持移植而来)。 To some extent,
std::vector
makes this extension available in a more portable form.在某种程度上,
std::vector
使这个扩展以更便携的形式可用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.