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;
}