5

In C++ various options are possible to pass arguments to functions (pass by value, reference, pointer, reference to const, pointer to const, ...). I was wondering what the Fortran analogue would be for all these options. This analogue would be from a concept point of view, and not an interoperability point of view.

As far as I know, Fortran passes its arguments by reference, with some exceptions to this rule (non-contiguous arrays). With this in mind, are the following conversions correct, or are there better attributes that can be given?

  • void f(X x); // Pass by value

    This is a mere copy of the original value that is passed

    SUBROUTINE f(x)
       TYPE(X), VALUE :: x
       ...
    END SUBROUTINE f
    
  • void f(X &x); // Pass by reference

    Here x is a reference whose value is updated. As pass by reference is the "default" in Fortran, I see two possible options remaining: the argument an INTENT(OUT) or INTENT(INOUT)

    SUBROUTINE f(x)
       TYPE(X), INTENT([IN]OUT) :: x
       ...
    END SUBROUTINE f
    
  • void f(X const &x); // Pass by reference-to-const

    Here x is a reference whose value cannot be updated.

    SUBROUTINE f(x)
       TYPE(X), INTENT(IN) :: x
       ...
    END SUBROUTINE f
    
  • void f(X *p); // Pass by pointer

    This is a mere copy of a pointer that is passed. However, this would imply that the attributes POINTER and VALUE should be combined, but this is not allowed in Fortran. The only alternative I can imagine is

    SUBROUTINE f(x)
       TYPE(X), INTENT(INOUT) :: x
       TYPE(X), POINTER :: p => x
       ...
    END SUBROUTINE f
    
  • void f(X const *p); // Pass by pointer-to-const

    Here p is a pointer pointing to a const which is copied over. This is, however, the same problem as with f(X *p)

    SUBROUTINE f(x)
       TYPE(X), INTENT(IN) :: x
       TYPE(X), POINTER :: p => x
       ...
    END SUBROUTINE f
    
  • void f(X * const p); // Pass by const-pointer

    Here p is a pointer that cannot change, but the object it points to can. Again p is a copy and not a reference

    SUBROUTINE f(x)
       TYPE(X), INTENT(INOUT) :: x
       TYPE(X), POINTER, PARAMETER :: p => x
       ...
    END SUBROUTINE f
    
  • void f(X const * const p); // Pass by const-pointer

    Here p is a pointer that cannot change and neither can the object it points to. Again p is a copy and not a reference

    SUBROUTINE f(x)
       TYPE(X), INTENT(IN) :: x
       TYPE(X), POINTER, PARAMETER :: p => x
       ...
    END SUBROUTINE f
    
  • void f(X * & p); // Pass by reference-to-pointer

    This is a reference to a pointer, both p and the object it points to can change.

    SUBROUTINE f(p)
       TYPE(X), POINTER, INTENT([IN]OUT) :: p
       ...
    END SUBROUTINE f
    
  • void f(X const * & p); // Pass by reference-to-pointer-to-const

    Here p references a pointer to a constant object. There seems to be no analogue here.

  • void f(X * const & p); // Pass by reference-to-const-pointer

    Here p is a reference to a pointer that cannot change, but the object it points to can.

    SUBROUTINE f(p)
       TYPE(X), POINTER, INTENT(IN) :: p
       ...
    END SUBROUTINE f
    
  • void f(X const * const & p); // Pass by reference-to-const-pointer-to-const

    Here p is a reference to a pointer that cannot change, and neither can the object it points to. Is there an analogue here?

kvantour
  • 25,269
  • 4
  • 47
  • 72
  • You just had to tag every language that you could think of, when this question is all about Fortran, and perhaps minimally of Fortran and C++. – Antti Haapala -- Слава Україні Nov 09 '17 at 15:38
  • Why do you think that non-contiguous arrays are exceptions to pass-by-reference? – francescalus Nov 09 '17 at 15:43
  • Are you asking, fundamentally: what are the Fortran equivalent of these C++ constructs? Without motivation, as you say it isn't about interoperability, I don't know that that's a meaningful or useful question, especially as Fortran itself has very little to say about implementation details like this. Yes, the various dummy argument attributes make sense _within Fortran_, but it may be easier to ask directly what each means. – francescalus Nov 09 '17 at 15:45
  • 1
    @francescalus It is sometimes possible that temporary arrays are created when an argument is passed onto a function and/or copied back after execution. The latter depends on the intent attribute given to the dummy-argument. Hence, as a copy is made, I considered them not really the same as pass-by-reference even though the end-result is the same. – kvantour Nov 09 '17 at 16:23
  • 2
    Non-contiguous array actual arguments may indeed involve copy-in/copy-out, or they may not, but that is not too much depending on whether there is an intent attribute or what it is. Your last sentence in the comment is very important: how argument passing happens is not important, as long as the required effects are observed. Copy-in/out, by-value, by-reference are not simply determined by intent or other attributes. – francescalus Nov 09 '17 at 16:38
  • @francescalus what I meant to say was that the copy-in/copy-out _could_ depend on the INTENT attribute. i.e. INTENT(in) only needs a copy-in, INTENT(out) only an out and INTENT(inout) both. Nonentheless, eventhough the end-result might be the same, I do think it is important to know how arguments are passed to a function as copies _could_ lead to memory problems (this however in an extreme case). – kvantour Nov 09 '17 at 17:33
  • You may find [this question](https://stackoverflow.com/q/45157027/3157076), and the ones linked from there, partly relevant. – francescalus Nov 09 '17 at 21:10
  • 2
    Intents are really not the thing to look at. Look at what kind of array you are passing. Is it contiguous? Does the compiler know it is contiguous at the compilation time? Is the argument you are passing to assumed shape assumed size or explicit size? Is it pointer or allocatable or value? Intents are the least important bit here. – Vladimir F Героям слава Nov 11 '17 at 09:42
  • 2
    And note that even `VALUE` is passed using an address. But it is an address of a copy. – Vladimir F Героям слава Nov 11 '17 at 09:44
  • In the second example, I guess intent(out) may be what OP does not want (i.e. intent(inout) or no intent seems more appropriate here, to me) because a compiler might make use of arguments of intent(out) as a work space internally (which I read somewhere before but not very sure...) and also user-defined finalization could occur automatically (?) if defined in the type. I guess both of them do not occur in the corresponding C++ example (with just X&). – roygvib Nov 11 '17 at 14:51
  • @AnttiHaapala since this was my first activity on SO, I did not really fully understand when to tag what. I have now edited this to remove the superfluous tags. I know, a bit late, but it takes time to understand how SO works. – kvantour Jul 27 '18 at 14:24

0 Answers0