2

I have two derived types in a module, Interval and Inrset. Both have same functionality, however one operates on reals, the other on integers.

The problem being encountered is as follows

lib/interval.f:85:11:

Procedure :: eptset => inrval_set
        1
Error: Argument 't' of 'inrval_set' with PASS(t) at (1) 
must be of the derived-type 'inrset'

lib/interval.f:55:11:

Procedure :: eptset => inrval_set
        1
Error: Argument 't' of 'inrval_set' with PASS(t) at (1) 
must be of the derived-type 'interval'

Here is the Interval derived type

Type Interval

Real (Real32) :: inf, sup

Contains
  Procedure :: eptset => inrval_set

End Type Interval

And this is is the Intrset derived type

Type Inrset

Integer (Int32) :: inf, sup

Contains
  Procedure :: eptset => inrval_set

End Type Inrset

This shall be the common subroutine for setting inf and sup.

Subroutine inrval_set  &
  (                    &
    t, inf, sup        &
  )

Class (*), Intent (InOut) :: t
Class (*), Intent (In) :: inf, sup

!!$--------------------------------------------------
!!$ Sets t% inf = inf;  t% sup = sup

Select Type (t)
Type Is (Interval)
  Call numtrf (t% inf, inf)
  Call numtrf (t% sup, sup)

Type Is (Inrset)
  Call numtrf (t% inf, inf)
  Call numtrf (t% sup, sup)

End Select 

End Subroutine inrval_set
Zeus
  • 1,485
  • 1
  • 17
  • 33
  • 2
    Do you want to know why what you are trying to do is wrong, or another approach to do what you want? – francescalus Jul 16 '15 at 14:08
  • I am looking for an approach that might work. I already had separate routines for each type which worked. It would help to understand what is happening with this code though. – Zeus Jul 16 '15 at 14:29
  • It is demanding that I have separate subroutines for each case. Is there a good workaround, or do I have to rethink the approach? – Zeus Jul 16 '15 at 14:36
  • Well, if you have to different types, you need two different type bound procedures, each having the right passed dummy argument. That is what the error is saying. How to best design your program is a different issue. – Vladimir F Героям слава Jul 16 '15 at 14:42

1 Answers1

2

Error messages are, admittedly, not always helpful. In this case it is a good prompt.

Your derived type Interval has a type-bound procedure with binding name eptset and interface the same as the procedure inrval_set. This is your difficulty.

I imagine you have in mind a call like

type(Interval) range
call range%eptset(1._real32, 15._real32)

which is a reasonable goal.

However, you are relying on a passed-object dummy argument, so that in inrval_set your first dummy argument t is of dynamic type range. This is flawed.

As the error message suggests, the interface for the type-bound procedure in Interval must, because it doesn't have the NOPASS attribute, have a dummy argument of type Interval. A dummy argument of class(*) is not such a thing.

You don't want to do this approach using NOPASS.

You could, of course, have

call inrval_set(range, 1._real32, 15._real32)

as one option. But are there type-bound ways?

Yes.

You could consider templating. Or, have an (abstract) parent class. Or provide type-bound procedures with the appropriate interface - one for each type.

Essentially, you're repeating code in the select type block, so you may as well repeat the code with generic/dynamic resolution instead.

francescalus
  • 30,576
  • 16
  • 61
  • 96
  • I see. Noticed that when templating, in the `.inc` file no types are assigned. – Zeus Jul 16 '15 at 14:59
  • Can you give me some explanation on the `NOPASS` idea. – Zeus Jul 16 '15 at 15:04
  • You can read about `nopass` in the usual references. I won't explain here, as it's really not something you want to do. `nopass` just means that the called procedure won't have a passed-object dummy argument. But that's what you want, because you want to set values of that object. It does allow you to do `call range%eptset(range, ..., ...)` (possibly), but that that point you may as well just `call inrval_set(range, ..., ...)`. – francescalus Jul 16 '15 at 15:13
  • Yes. I have used pass when I coded some operators where the first dummy argument was not typed to the derived type name. I aqree with you that I want a type bound procedure rather than calling `inrval_set(range, ..., ...)`. – Zeus Jul 16 '15 at 15:21
  • More about templating also here http://stackoverflow.com/questions/24979199/stl-analogue-in-fortran/24979275#24979275 . You will see how to get power for the types using `#include` instead of `include`. – Vladimir F Героям слава Jul 16 '15 at 16:29