简体   繁体   English

在带有模板的函数中传递未知大小的 std::Array。 如何更正此代码?

[英]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 :模板参数_SizesizeY,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.必须在编译时知道数组(或一般模板参数)的大小,因此无法使用运行sizeXsizeY作为数组的大小(模板参数)。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM