-
Notifications
You must be signed in to change notification settings - Fork 0
/
container.f90
105 lines (89 loc) · 3.72 KB
/
container.f90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
module container_mod
implicit none
private
public :: container_tmpl
requirement R(T, U, V)
type :: T; end type
type :: U; end type
type :: V; end type
end requirement
! NOTE: Had to add a new generic type V here even though it is not used in the type
template container_tmpl(T, U, V)
requires R(T, U, V)
private
public :: container_t
type :: container_t
type(T) :: first
type(U) :: second
contains
procedure :: swapped
procedure :: copy_first
procedure :: only_first
end type
contains
function swapped(this) result(container)
! QUESTION: Will recursive template instantiation be allowed?
! NOTE: This is NOT instantiation! container_u_t_t is still generic.
instantiate container_tmpl(U, T), only: container_u_t_t
class(container_t), intent(in) :: this
type(container_u_t_t) :: container
container%first = this%second
container%second = this%first
end function
function copy_first(this, second) result(container)
! NOTE (as above): This is NOT instantiation! container_t_v_t is still generic.
instantiate container_tmpl(T, V), only: container_t_v_t
class(container_t), intent(in) :: this
type(container_t_v_t) :: container
container%first = this%first
container%second = this%second
end function
function only_first(this) result(container)
! NOTE (as above): This is NOT instantiation! container_t_t_t is still generic.
instantiate container_tmpl(T, T), only: container_t_t_t
class(container_t), intent(in) :: this
type(container_t_t_t) :: container
container%first = this%first
container%second = this%first
end function
real function add_both(this) result(sum)
! NOTE: Possibly a way of additional restrictions to generic type arguments
! for type bound procedures
requirement
integer :: T
integer :: U
end requirement
class(container_t), intent(in) :: this
sum = this%first + this%second
end function
end template
end module
program main
use container_mod, only: container_tmpl
implicit none
! NOTE: Cheating here, V as integer is never used for a
instantiate container_tmpl(integer, real, integer), only: container_int_real_t => container_t
! NOTE: This will become problematic if we want to use `copy_first` with another type
instantiate container_tmpl(real, integer, character(len=:)), only: container_real_int_t => container_t
! NOTE: Cheating here, V as integer is never used for c
instantiate container_tmpl(real, character(len=:), integer), only: container_real_chars_t => container_t
! NOTE: Cheating here, V as integer is never used for d
instantiate container_tmpl(real, real, integer), only: container_real_real_t => container_t
type(container_int_real_t) :: a
type(container_real_int_t) :: b
type(container_real_chars_t) :: c
type(container_real_real_t) :: d
real :: sum
a = container_int_real_t(1, 2.5)
write(*,*) 'first = ', a%first, ' second = ', a%second
b = a%swapped()
write(*,*) 'first = ', b%first, ' second = ', b%second
c = b%copy_first("Hello world")
write(*,*) 'first = ', c%first, ' second = ', c%second
d = b%only_first()
write(*,*) 'first = ', d%first, ' second = ', d%second
sum = d%add_both()
write(*,*) 'sum = ', sum
! NOTE: This would be a compile error
! sum = c%add_both()
end program