Giter VIP home page Giter VIP logo

Comments (3)

milancurcic avatar milancurcic commented on July 23, 2024

Thanks, indeed, the intent(in) arguments to specific procedures that overload the operators are defined as class by design, so that these operators can work for sub-classes out of the box.

But in your case, you actually want to override the inherited operator with a new procedure. Certainly valid. To be honest, I don't know what the standard says about this, but I'd think that you should be able to override the inherited operator with a new one.

Can you please post the code for RelativeDelta and datetime_plus_relativedelta, and let me know the compiler and version you are working with?

In the meantime I will try to reproduce this in a minimal example.

from datetime-fortran.

DaisukeTokuda avatar DaisukeTokuda commented on July 23, 2024

I appreciate your reply and I apologize much longer post.
I use ifort, Intel(R) Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 19.0.3.199 Build 20190206.

The implementation of RelativeDelta and datetime_plus_relativedelta are as below. Since I defined RelativeDelta for I/O of monthly/yearly data in numerical simulation, I prohibited both of (years or months) and timedelta have non-zero value in the constructor.
The following code defines operator(+) as a external function out of the class, however the code does not work even if the operator(+) is defined as an in-class method like your implementation in mod_datetime.f90.

type, extends(TimeDelta) :: RelativeDelta
    private
    integer years, months
    contains
    procedure :: getYears      => getYears
    procedure :: getMonths  => getMonths
! for in-class method
!    procedure, pass(dt) :: datetime_plus_timedelta => datetime_plus_relativedelta
!    procedure :: timedelta_plus_datetime => relativedelta_plus_datetime
!    generic   :: operator(+) => datetime_plus_timedelta, timedelta_plus_datetime
end type RelativeDelta

interface RelativeDelta
    module procedure init_relativedelta
end interface RelativeDelta

interface operator(+)
    module procedure datetime_plus_relativedelta
    module procedure relativedelta_plus_datetime
end interface operator(+)

contains ! constructor, getYears() and getMonths are also defined

pure elemental function datetime_plus_relativedelta(t1, dt) result(t2)
    type(DateTime),      intent(in) :: t1
    type(RelativeDelta), intent(in) :: dt
! for in-class method
!    class(DateTime),      intent(in) :: t1
!    class(RelativeDelta), intent(in) :: dt
    type(DateTime)                  :: t2
    integer :: iyear, imon, years, mons
    t2 = t1
    years = dt%getYears()
    do iyear = 1, years
        t2 = t2 + TimeDelta(days=daysInYear(t2%getYear()))
    enddo

    mons = dt%getMonths()
    do imon = 1, mons
        t2 = t2 + TimeDelta(days=daysInMonth(t2%getMonth(), t2%getYear()))
    enddo

    t2 = t2 + dt%TimeDelta
end function datetime_plus_relativedelta

Test case is:

program main
    implicit none
    call relativedelta_test
contains

subroutine relativedelta_test
    use datetime_ext_mod
    type(DateTime)       :: t1, t2
    type(RelativeDelta) :: dt
    t1 = DateTime(2000, 1, 1)
    dt = RelativeDelta(years=1)
    t2 = t1 + dt
    write(*, '(3i2,2a)') dt%getYears(), dt%getMonths(), dt%getHours(), ' ', t2%strftime('%Y/%m/%d %H:%M')

    dt = RelativeDelta(months=1)
    t2 = t1 + dt
    write(*, '(3i2,2a)') dt%getYears(), dt%getMonths(), dt%getHours(), ' ', t2%strftime('%Y/%m/%d %H:%M')

    dt = RelativeDelta(hours=1)
    t2 = t1 + dt
    write(*, '(3i2,2a)') dt%getYears(), dt%getMonths(), dt%getHours(), ' ', t2%strftime('%Y/%m/%d %H:%M')

end subroutine relativedelta_test
end program main

Output is:

 1 0 0 2000/01/01 00:00
 0 1 0 2000/01/01 00:00
 0 0 1 2000/01/01 01:00  <- executed + for timedelta instead of relativedelta

I'm afraid that my current solution has to modify YOUR module:

  • remove datetime_plus_timedelta and timedelta_plus_datetime from in-class method of datetime
  • change the attribute of arguments of datetime_plus_timedelta and timedelta_plus_datetime from class to type
  • re-define operator(+) out of datetime class as below (and make it public)
interface operator(+)
  module procedure :: datetime_plus_timedelta
  module procedure :: timedelta_plus_datetime
end interface

Is there any smarter way to overload the operator?

from datetime-fortran.

milancurcic avatar milancurcic commented on July 23, 2024

Hi Daisuke,

Sorry about the delay with this. I agree with your conclusion--because the operators are defined as type-bound methods rather than regular procedures, they require class for the input argument.

The solution you propose would work for your use case, however it would break the use case of extended datetime and timedelta types inheriting the original operators.

I can't think of any way to make both functionalities work with the same code, however if I do I will write here.

I see that you have two options:

  1. Roll your own fork of datetime with your modifications;
  2. Use custom operators instead of built-in arithmetic. For example, you could define your .add. operator for the extended types, instead of +. Less elegant, but works.

from datetime-fortran.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.