Attempting type erasure in Fortran

At the time I didn’t have a name for, but a past post from @Arjen also fits under the spirit of type erasure. In that thread the challenge was to write a generic “reverse” subroutine.

Reversing an array, only requires that the types are assignable so you can swap their contents:

subroutine reverse( array, assign )
    class(*), dimension(:), intent(inout), pointer     :: array  
       ! (25/9/2022, is pointer attribute needed?)
    interface
        subroutine assign( a, b )
            class(*), intent(out) :: a
            class(*), intent(in)  :: b
        end subroutine assign
    end interface

    class(*), allocatable                              :: tmp
    integer                                            :: i, j

    allocate( tmp, mold=array(1) )

    do i = 1,size(array)/2
        j        = size(array) + 1 - i
        call assign( tmp, array(i) )
        call assign( array(i), array(j) )
        call assign( array(j), tmp )
    enddo
end subroutine reverse
end module reverse_array

For each type you’d like to swap, you need a subroutine such as:

subroutine assign_person( a, b )
    class(*), intent(out) :: a
    class(*), intent(in)  :: b
    select type( a )
        type is (person)
            select type( b )
                type is (person)
                    a = b
            end select
    end select
end subroutine assign_person

It’s not difficult to see, you just replace person with any type, and you can reuse the reverse routine. It seems very close to what C++20 concepts are for:

// reverse.cpp

#include<concepts>
#include<vector>
#include<iostream>
#include<string>

template<typename T>
concept Assignable = requires(T a, T b) {
    a = b;
};

template<Assignable T>
void reverse(std::vector<T> &array) {

    int n = array.size();
    for (int i = 0; i < n/2; ++i) {
        int j = n - i - 1;
        T tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }    
}

template<class Array>
void show(std::string title, Array c) {
    std::cout << title << " = [ ";
    for(int i = 0; i < c.size(); ++i) {
        std::cout << c[i] << " ";
    }
    std::cout << "]\n";
}

int main(int argc, char const *argv[]) {

    std::vector<int> arr{1,2,3,4,5};
    
    show("      initial",arr);
    reverse(arr);    
    show("after reverse",arr);

    return 0;
}