less verbose way to declare multidimensional std::array

前端 未结 5 732
再見小時候
再見小時候 2020-12-05 11:11

Short question: Is there a shorter way to do this

array,n>,m> matrix;

I was hoping for something like

相关标签:
5条回答
  • 2020-12-05 11:32

    Here's a simple, generic version:

    template <typename T, size_t d1, size_t d2, size_t... ds>
    struct GetMultiDimArray
    {
        using type = std::array<typename GetMultiDimArray<T, d2, ds...>::type, d1>;
    };
    
    template <typename T, size_t d1, size_t d2>
    struct GetMultiDimArray<T, d1, d2>
    {
        using type = std::array<std::array<T, d2>, d1>;
    };
    
    template <typename T, size_t d1, size_t d2, size_t... ds>
    using MultiDimArray = typename GetMultiDimArray<T, d1, d2, ds...>::type;
    
    // Usage:
    MultiDimArray<int, 3, 2> arr {1, 2, 3, 4, 5, 6};
    assert(arr[1][1] == 4);
    
    0 讨论(0)
  • 2020-12-05 11:44

    A palatable workaround for compilers that don't support template aliases yet is to use a simple metafunction to generate the type:

    #include <cstddef>
    #include <array>
    
    template<class T, std::size_t RowsN, std::size_t ColumnsN>
    struct Matrix
    {
        typedef std::array<std::array<T, ColumnsN>, RowsN> type; // row major
    
    private:
        Matrix(); // prevent accidental construction of the metafunction itself
    };
    
    int main()
    {
        Matrix<int, 3, 4>::type matrix;
    }
    
    0 讨论(0)
  • 2020-12-05 11:44

    Solution using variadic templates (slightly more complex than the template alias, but more general purpose)

    template <typename T, std::size_t thisSize, std::size_t ... otherSizes>
    class multi_array : private std::array<multi_array<T, otherSizes...>, thisSize>
    {
     using base_array = std::array<multi_array<T, otherSizes...>, thisSize>;
    
     public:
        using base_array::operator[];
        // TODO: add more using statements to make methods
        // visible.  This is less typing (and less error-prone)
        // than forwarding to the base_array type.
    };
    
    template <typename T, std::size_t thisSize>
    class multi_array<T, thisSize> : private std::array<T, thisSize>
    {
     using base_array = std::array<T, thisSize>;
    
     public:
        using base_array::operator[];
        // TODO: add more using statements to make methods
        // visible.  This is less typing (and less error-prone)
        // than forwarding to the base_array type.
    };
    

    There might be some improvement on assigning to non-leaves of the array that could be made.

    I tested with a relatively recent build of clang/LLVM.

    Enjoy!

    0 讨论(0)
  • 2020-12-05 11:45

    When nested, std::array can become very hard to read and unnecessarily verbose. The opposite ordering of the dimensions can be especially confusing.

    For example:

    std::array < std::array <int, 3 > , 5 > arr1; 
    

    compared to

    char c_arr [5][3]; 
    

    Also, note that begin(), end() and size() all return meaningless values when you nest std::array.

    For these reasons I've created my own fixed size multidimensional array containers, array_2d and array_3d. They have the advantage that they work with C++98.

    They are analogous to std::array but for multidimensional arrays of 2 and 3 dimensions. They are safer and have no worse performance than built-in multidimensional arrays. I didn't include a container for multidimensional arrays with dimensions greater than 3 as they are uncommon. In C++11 a variadic template version could be made which supports an arbitrary number of dimensions (Something like Michael Price's example).

    An example of the two-dimensional variant:

    //Create an array 3 x 5 (Notice the extra pair of braces) 
    fsma::array_2d <double, 3, 5> my2darr = {{ 
    { 32.19, 47.29, 31.99, 19.11, 11.19}, 
    { 11.29, 22.49, 33.47, 17.29, 5.01 }, 
    { 41.97, 22.09, 9.76, 22.55, 6.22 } 
    }};  
    

    Full documentation is available here: http://fsma.googlecode.com/files/fsma.html

    You can download the library here: http://fsma.googlecode.com/files/fsma.zip

    0 讨论(0)
  • 2020-12-05 11:53

    A template alias might help out:

    #include <array>
    
    template <class T, unsigned I, unsigned J>
    using Matrix = std::array<std::array<T, J>, I>;
    
    int main()
    {
        Matrix<int, 3, 4> matrix;
    }
    
    0 讨论(0)
提交回复
热议问题