template<typename T>
void Transpose(T** Data, std::size_t Size)
{
    for (int I = 0; I < Size; ++I)
    {
        for (int J = 0; J < I; ++J)
        {
            std::swap(Data[I][J], Data[J][I]);
        }
    }
}


int main()
{
    int A[4][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12},
        {13, 14, 15, 16}
    };

    int* Ptr = &A[0][0];
    int** P = &Ptr;

    Transpose(P, 4);   //ERROR! Access Violation.
}

Versus:

int main()
{
    int** B = new int[4];
    for (int I = 0, K = 1; I < 4; ++I)
    {
        B[I] = new int[4];
        for (int J = 0; J < 4; ++J)
        {
            B[I][J] = K++;
        }
    }

    Transpose(B, 4);  //Works fine..
}

So how can I distinquish the difference? In other words, how can I figure out which kind of T** they are passing?

You might need a parameter that defines the number of fields in the array and number of elements in each field.

Edited 3 Years Ago by tinstaafl

So how can I distinquish the difference? In other words, how can I figure out which kind of T** they are passing?

You can't. There is no difference between T** (pointing to an array of arrays) and T** (pointing to a pointer to a T variable) from a type perspective. You can file it under "another reason not to use C-style arrays".

When using a "strongly typed" language, if you wish to benefit from static type checking, it is your responsibility to correctly and strictly encode the requirements of the passed parameters into their type. A type like T** does not enforce any requirement other than "it must point to a pointer to T". The requirement that the first parameter should actually refer to an array of arrays is not well represented by the type that you used for that parameter. The compiler can only enforce the requirements that you laid out.

The solution here is that you should have some other type that would be more strict. This could simply take the form of std::vector< std::vector< T > >, or some other more general type. Maybe a custom type like Matrix<T> or something like that. Otherwise, you'll have to accept that this function is just weakly typed, and cannot ensure, statically, that the passed parameter is truly of the correct type.

This question has already been answered. Start a new discussion instead.