	#include <iostream>
	#include <typeinfo>

    struct Type {};

    // 1: Array of Type*.
    void func(Type *arr [3]) {
        std::cout << "Type* array.\n"
                  << typeid(arr).name() << "\n\n";
    }

    // 2: Array of Type&.
    // Illegal.
    // void func(Type &arr [3]) {
    //     std::cout << "Type& array.\n"
    //               << typeid(arr).name() << "\n\n";
    // }

    // 3: Pointer to array of Type.
    void func(Type (*arr) [3]) {
        std::cout << "Pointer to Type array.\n"
                  << typeid(arr).name() << "\n\n";
    }

    // 4: Reference to array of Type.
    void func(Type (&arr) [3]) {
        std::cout << "Reference to Type array.\n"
                  << typeid(arr).name() << "\n\n";
    }
    
    int main() {
        // Array of Type.
        Type   t_arr[3] = {};

        // Array of Type*.
        Type* tp_arr[3] = { &t_arr[0], &t_arr[1], &t_arr[2] };

        // Array of Type&.
        // Illegal.
        // Type& tr_arr[3] = { t_arr[0], t_arr[1], t_arr[2] };

        std::cout << "Type[3]: " << typeid(t_arr).name() << "\n\n";
        
        func(t_arr);  // Calls #4.
        func(&t_arr); // Calls #3.
        func(tp_arr); // Calls #1.
    }
