@namark The real question in my eyes is, why not? Sounds like the only argument against it that you have is that you need to guard against division by 0, which is almost certainly insignificant in terms of performance in viertually all situations. In fact the only way that tiny guard could even possible matter is if there is some alorithm that spends time creating a hell of a of times over very short time spans, even then its unlikely.
In fact if someone consuming your timer actually ran code where that guard had any meaningful effect to them on performance then they probably wouldnt be calling it with 0 or using a timer in the first polace and would hand roll a more efficient approach.
So yea, I'd say 0 should absolutely be a valid value.
What I wouldnt do though is make it the default value as you suggest. I would make the value required and thus have no default. Also if you really want to be pedantic you could probably write it so it could have the 0 allowed value and not need the guard at all. Exactly how would depend on the language and the specific design but it would probably involve making some function or aspect a constant at the time the timer is constructed such that you'd have a singleton "0 timer" which would be returned anytime a timer of 0 is asked for.
@freemo You can add a specific language context you are most familiar with. I'm curious about any perspective, even if it's specific.
I wield the c++ chrono library and my ambition is to forge the timer to rule them all and in the darkness bind them *evil laugh*. I don't want people writing their own timers, what is this frivolity?!
I'm not sure what creation of timers have to do with the zero guard. Timer being just a number or two, creation cost is negligible, and the division does not occur during creation, but when checking the progress ratio, which can happen quite often. Say, in context of animation that can be every screen refresh, and there can be a lot of timers involved, as their are used for "inbetweening" (go from A to B in X time). In a more general sense though, the ratio calculation is just a division, usually one instruction, and adding the guard can add a significant relative overhead (I don't know 30-100% maybe). It might not matter, but I want to cover the cases where it matters as well.
The default initialization is usually considered a good thing if it's meaningful, since it's what the basic value types do. As in "here is my super simple type, if you can handle an int, you can hand it as well". Especially if you allow initialization to any value and the value type has a common sense default, preventing default initialization is kind of wonky. There is very little difference between
Type(),
and
Type(0),
except that the latter requires the literal 0, which in context of time durations is a bit problematic, since it needs units. Even dealing with arithmetic types in generic code people will often prefer the default initialization to a literal 0, since the type in question might not want to be in general constructable from a single integer (2D vector that requires 2 integers, but also defaults to natural [0,0]) or the value corresponding to integer zero might not be the best default (additive identity for floats is -0).
A special "0 timer" type can't really solve the performance issue for a value not knows at compile time, since it would require some sort of dynamic polymorphism, that would likely generate a worse check and a worse branch that the simple guard would. For values knows at compile time, the compiler will like optimize the guard away, so it's really all about the runtime requirements.