Paul Chernoch
Paul Chernoch

Reputation: 5553

How do I phrase a function's type constraint to permit the addition of values of different types?

I intend to overload some operators, but am working my way up to it because the syntax is baffling. As an intermediate step, I am trying to write a function that adds two values that already support addition. My function will take as arguments values of types &A and B, call a function to turn B into a C, then clone the A so I can perform A + C to get another A and return it. To make it simple for this question, B is i64 and C is Duration from the chrono crate.

The part that confuses me is the type bounds. How do I say that you can add A + Duration to get another A (and get the lifetimes straight)? A is not Copy, but I am happy cloning it. Example types of A are Date and Datetime, which both implement the Datelike trait.

use std::ops;
use chrono::Duration;
use chrono::{Date, Datelike, offset::TimeZone};

fn add_datelike_and_duration<A>(a: &A, days: i64) -> A 
where A: Datelike + Clone,
... something I can't figure out ... 
{
   let duration = Duration::days(days);
   let new_a = a.clone() + duration;
   let modified_new_a: A = ... do more stuff ...
   modified new_a
}

What did not work was this:

for<'a> 'a + A: ops::Add<Output = A>

(Note: The function is a little more complex. I am turning a new kind of duration that is a number of years and months into an approximate number of days, adding them to the date, then moving forward or backward a few days to match the day of the month, unless the starting day is the 31st and we end up in a 30-day month, or end up in February. Months and years vary in how long they are, making this tricky. This is part of XPATH YearMonth duration support.)

Upvotes: 1

Views: 50

Answers (1)

trent
trent

Reputation: 27935

To say that A can be added to a Duration to yield another A:

A: ops::Add<Duration, Output = A>
//          ^^^^^^^^ add this part

The Add trait (along with most of the traits in std::ops) has a type parameter that defaults to Self, so when you write A: Add it means A: Add<A> and A: Add<Output = A> means Add<A, Output = A>. To add A to Duration you have to explicitly override this default.

Adding a lifetime ('a) is only necessary if you want to add references.

See also

Upvotes: 1

Related Questions