Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning fixed size array

Tags:

c++

If I have a fixed-size 2D array T array[M][N], I can access elements via array[i][j], and assert(sizeof(array[i]) == N * sizeof(T)).

How can I do it for array wrapped in a struct?

The following code allows to access elements via array[i][j] but fails the assert.

Is there a way for operator[] to return T[N] instead of T* ?

template<class T, int M, int N>
struct Array
{
    T data[M][N];

//  constexpr T[N] operator[] (int i) - CANNOT RETURN T[N]!
    constexpr T* operator[] (int i)
    {
        return data[i];
    }
}
like image 367
user2052436 Avatar asked Aug 19 '26 00:08

user2052436


2 Answers

Returning a reference-to-array gives the sizeof you were looking for:

template<class T, int M, int N>
struct Array
{
    T data[M][N];

//  constexpr T[N] operator[] (int i) - CANNOT RETURN T[N]!
    constexpr T (&operator[](int i))[N]
    {
        return data[i];
    }
};

int main()
{
    Array<double, 2, 3> a;
    std::cout << sizeof(a) << ", " << sizeof(a[1]);
}

Introducing a type alias makes it easier to read

using row = T[N]; // or typedef T (&row)[N]

constexpr row& operator[](int i)
{
    return data[i];
}
like image 78
Ben Voigt Avatar answered Aug 21 '26 13:08

Ben Voigt


The different ways to return reference to array C++98/C++03 compatible ways:

  • Ugly way:

    T (&operator[](int i))[N] { return data[i]; }
    
  • With typedef:

    typedef T arr[N];
    
    arr& operator[](int i) { return data[i]; }
    

    or:

    typedef T (&arr_ref)[N];
    
    arr_ref operator[](int i) { return data[i]; }
    

Since C++11, in addition we have:

  • with decltype:

    decltype(data[i]) operator[](int i) { return data[i]; }
    
  • trailing return type:

    auto operator[](int i) -> T(&)[N] { return &f; }
    

    or:

    auto operator[](int i) -> decltype(data[i]) { return data[i]; }
    
  • typedef with using:

    using arr = T[N];
    
    arr& operator[](int i) { return data[i]; }
    

    or:

    using arr_ref = T(&)[N];
    
    arr_ref operator[](int i) { return data[i]; }
    

Possibly with template using:

template <typename T, std::size_t N>
using CArray = T[N];

CArray<T, N>& operator[](int i) { return data[i]; }

C++14 adds:

  • auto deduction:

    auto& operator[](int i) { return data[i]; }
    
  • decltype(auto) (but careful with deduced return type):

    decltype(auto) operator[](int i) { return (data[i]); }
    

Alternatively, instead of C-array, using std::array would allow more natural syntax

like image 25
Jarod42 Avatar answered Aug 21 '26 14:08

Jarod42



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!