I find myself having to do many, many
.inSeconds() conversions in order to do simple additions and subtractions with
double. We have overloads for multiplication and division by
double (see below).
/** Multiplies a TimePosition by an ammount. */
[[ nodiscard ]] constexpr TimePosition operator* (const TimePosition&, double);
/** Divides a TimePosition by an ammount. */
[[ nodiscard ]] constexpr TimePosition operator/ (const TimePosition&, double);
/** Multiplies a TimeDuration by an ammount. */
[[ nodiscard ]] constexpr TimeDuration operator* (const TimeDuration&, double);
/** Divides a TimeDuration by an ammount. */
[[ nodiscard ]] constexpr TimeDuration operator/ (const TimeDuration&, double);
It would be great if we also had overloads for addition and subtraction by
/** Add and amount to TimePosition. */
[[ nodiscard ]] constexpr TimePosition operator+ (const TimePosition&, double);
/** Subtract and amount from a TimePosition. */
[[ nodiscard ]] constexpr TimePosition operator- (const TimePosition&, double);
/** Add and amount to a TimeDuration. */
[[ nodiscard ]] constexpr TimeDuration operator+ (const TimeDuration&, double);
/** Subtract and amount from a TimeDuration. */
[[ nodiscard ]] constexpr TimeDuration operator- (const TimeDuration&, double);
The code would be a lot cleaner with the new overloads. But I may be missing something.
What is the rationale for them not being there?
I think you’re missing the point of having them there in the first place. They’re specifically so you can’t add untyped doubles to them and it be ambiguous what you get back.
For example if you have a TimePosition and you add a double, does that double represent a Position (which wouldn’t be allowed) or a Duration (which would return another position).
Similarly when you subtract a Position/Duration from one another, the argument types determine the return types.
The existing double arithmetic is only there when there is no type. E.g. in
Duration * 2 the two is simply an untyped number. A
Duration * Duration wouldn’t make any sense.
The real question should be why do you have doubles in the first place? What do they actually represent?
Thank you, that is why I asked. I wanted to know the rationale.
I have already updated all the code in my DAW, and everything works.
My comment was about how verbose the code is now, and the constant conversion to and from seconds. Previously I used good variable naming to keep beats and seconds from getting confused, which resulted in more concise code.
Actually it is fairly common to need to add small double values (seconds) to nudge notes or clips around. How did you intend this to be done?
As I said though, I have already adopted the new paradigm so I will get used to it.
In theory your code shouldn’t be much more verbose, just stricter and the type system will help you catch misuse.
Have you read the transition document? In that there are details of some literal suffixes that can be used to nudge things around e.g.
numBeats + 0.0001_bd.
Because Time is compatible with std::chrono you can use chrono suffixes for some really nice code e.g.
duration + 1ms.
There’s only two real places code should get more verbose: firstly if you convert between durations/positions, that’s deliberately obvious with
toPosition/toDuration. The second is because their only mutable by assignment so you can’t do
+= etc. anymore.
The latter can be a bit of a pain but we found having largely immutable types leads to more understandable code.
Ah, yes, the literals,
_tp, etc. Yes, that does help.
Good to know the std::chrono suffixes work too! That is very nice!