Search code examples
c++pointersdecltype

Use decltype to declare the return type


I've got the following code snippet:

int odd[] = { 1,3,5,7,9 };
int even[] = { 0,2,4,6,8 };

// returns a pointer to an array of five int elements
decltype(odd) *arrPtr(int i) {
    return (i % 2) ? &odd : &even; // returns a pointer to the array
}

int main()
{
    int *res1 = arrPtr(3);
    decltype(odd) *res2 = arrPtr(3);
    auto res3 = arrPtr(3);
}

For the first line I get the following error message:

int (*arrPtr(int i))[5]

returns a pointer to an array of five int elements

Error: a value of type "int (*)[5]" cannot be used to initialize an entity of type "int *"

Why can't int* be used to initialize my return value from arrayPtr()? I would have assumed that the compiler is doing an explicit conversion.

Furthermore, what would one use as return type (best practice)?


Solution

  • It seems odd is declared as an array of int:

    int odd[5];
    

    The type of odd is int[5] and taking the address (or adding a * to decltype(odd)) of this array yields an int(*)[5]. It seems, you actually want to use the decayed type of odd:

    decltype(+odd) arrPtr(int i) {
        return i % 2? odd: even;
    }
    
    int main() {
       int*           res1 = arrPtr(3);
       decltype(+odd) res2 = arrPtr(3);
       auto           res3 = arrPtr(3)
    }
    

    Note this use of unary + which forces decay of the array to become a pointer to the first element of the array.

    If you really mean to return a pointer to the array, you'd need to use a suitable type when capturing the result (assuming the original implementation):

    int (*res1)[5]      = arrPtr(3);
    decltype(odd)* res2 = arrPtr(3);
    auto res3           = arrPtr(3);
    

    Note, that this is a pointer to an array of 5 int, i.e., you'd access an element of it using

    (*res1)[3];
    

    or

    res1[0][3];