2

I make huge use of non-1 indexed ALLOCATABLE arrays, whose actual lower (and thus upper) bounds I want to be known for the procedures they're given to as IN/INOUT args (so I declare these dummy arguments as deferred-shape arrays to make them be passed along with their bounds; see f_deferred_all in the example code).

But.

Sometimes these procedures (after the data-declaration part) can deal with actual arguments being subarrays, so when this is needed, I usually end up making a copy of the procedure, changing its argument declaration along with its name (cf. procedure f_assumed). And it would be nice to put both procedures under the same name by means of an INTERFACE. But the standard says I cant, since

Interfaces of specific procedures or bindings are distinguished by fixed properties of their arguments, specifically type, kind type parameters, rank, and whether the dummy argument has the POINTER or ALLOCATABLE attribute.

In the following example program, I overcame this "limitation" by using pointer actual and dummy arguments (see f_deferred_ptr).

  1. Is this "solution" somehow deprecated, discouraged, dangerous or anything else? I ask this because I really haven't been using POINTERs so much.

In addition, I defined a pntr function that returns a POINTER to its sole (non-ALLOCATABLE array or section of an array) INput argument, so that I can use it "in-line" without defining a POINTER in the main program and I don't have to put the TARGET attribute on the actual arguments.

  1. Do I have, by using pntr, a temporary array be created? I think yes, but I'm not sure whether defining the POINTER and associate it in the main program would make a difference in this respect or not.
  2. Would it be possible/is it planned/would it make sense for the standard to be changed to allow such distinction between generics? Where is it to post such suggestions, provided they make sense?

Here the example follows.

module mymod

    implicit none

    interface f
        module procedure f_deferred_all, f_deferred_ptr!, f_assumed
    end interface f

    contains

    integer function f_assumed(x) result(y)
        integer, dimension(:), intent(in)  :: x
        y = lbound(x,1)
    end function f_assumed

    integer function f_deferred_ptr(x) result(y)
        integer, pointer,     dimension(:), intent(in) :: x
        y = lbound(x,1)
    end function f_deferred_ptr

    integer function f_deferred_all(x) result(y)
        integer, allocatable, dimension(:), intent(in) :: x
        y = lbound(x,1)
    end function f_deferred_all

    function pntr(v) result(vp)
        integer, dimension(:), target, intent(in)  :: v
        integer, dimension(:), pointer             :: vp
        vp => v
    end function pntr

end module mymod

program prog

    use mymod

    implicit none

    integer :: i
    integer, dimension(-5:5)           :: v1
    integer, dimension(:), allocatable :: v2

    v1 = [(i, i = 1, 11)]
    allocate(v2, source = v1)

    print *, 'f_assumed(v1)', f_assumed(v1)
    print *, 'f(pntr(v1))', f(pntr(v1(:))) ! is a temporary created?
    print *, 'f(v2)', f(v2)

end program prog
Enlico
  • 23,259
  • 6
  • 48
  • 102
  • A note: a module should be placed *before* the main program. I am quite surprised it compiles for you. – Vladimir F Героям слава Jan 21 '18 at 17:37
  • Oh, thank you! Fortunately I was using two separate files for the program and the module. – Enlico Jan 21 '18 at 17:41
  • 1
    I can't answer your question, but note that `v1` still needs the target attribute: the function result of `pntr` is pointer associated with the dummy argument `v`so `v1` not having the target attribute means that the function result becomes of undefined association status as soon as the function completes. – francescalus Jan 21 '18 at 18:44
  • (I hope my question does make sense, at least.) Are you saying that `f` in `f(pntr(v1(:)))` returns the correct value only by chance, depending on the compiler and other stuff? – Enlico Jan 21 '18 at 18:49
  • So far I am unable to understand what it is you'd like to do. What do you mean by "subarrays"? Please add a short code example that illustrates what you'd like to do, even if it doesn't work now. Do keep in mind that assumed-shape dummy arguments can take all kinds of arrays, including those with non-unit stride or even vector subscripts. – Steve Lionel Jan 23 '18 at 02:06
  • @SteveLionel, basically I'd like to uncomment the trailing part of the `module procedure` line, i.e. to be able to call `f(v2)` as well as `f(v1)`, `f(v2(3:))`, ... – Enlico Jan 23 '18 at 07:30
  • 1
    I think you have unnecessarily complicated this. All you need is the f_assumed function and therefore don't need a generic at all. – Steve Lionel Jan 23 '18 at 20:16

1 Answers1

4

Your example code is non-conforming because the specific names F_DEFERRED_PTR and F_DEFERRED_ALL are ambiguous. Technical Corrigendum f08/0001 changes the wording in "12.4.3.4.5 Restrictions on generic declarations", adding "and not the INTENT(IN) attribute", to

Two dummy arguments are distinguishable if
 • one is a procedure and the other is a data object,
 • they are both data objects or known to be functions, and neither is TKR compatible with the other,
 • one has the ALLOCATABLE attribute and the other has the POINTER attribute and not the INTENT(IN) attribute, or
 • one is a function with nonzero rank and the other is not known to be a function.

This is prompted by the fact that the actual argument for a POINTER, INTENT(IN) dummy can be a pointer or a valid target for the dummy pointer in a pointer assignment statement (12.5.2.7 Pointer dummy variables J3/10-007r1). Links to the discussion and resolution of the issue.