SFML community forums
General => General discussions => Topic started by: Laurent on January 13, 2012, 02:33:10 pm
-
Hi
Many users complained after I switched to milliseconds for time
http://www.sfml-dev.org/forum/viewtopic.php?t=4864
... this thread clearly shows that people need different resolutions and different types for representing time values.
I could of course provide the most precise (Uint64 nanoseconds) but that would not be simple -- user code would be pretty ugly.
So here is a proposal for a new time API, that is a little more verbose than before but should make everyone happy.
class Time
{
public:
Time();
float ToSeconds() const;
Int32 ToMilliseconds() const;
Int64 ToMicroseconds() const;
private:
Int64 myMicroseconds;
};
Time Seconds(float amount);
Time Milliseconds(Int32 amount);
Time Microseconds(Int64 amount);
class Clock
{
public:
Time GetElapsedTime() const;
...
}
void Sleep(Time duration);
// same in all functions that require/return a time value
User code:
sf::Clock clock;
sf::Time elapsed = clock.GetElapsedTime();
game.Update(elapsed.ToSeconds());
sf::Sleep(sf::Milliseconds(100));
sf::Time would be a time span, not a time point, so negative values would be allowed (hence the signed integers). It would have comparison and mathematical operators.
It could also support implicit conversions to/from std::chrono classes in the future.
-
Sounds good, although I'd tend to return a const reference to a Time member inside Clock (not sure about Time's structure).
What are the function calls after the class definition for? I'm a bit confused there.
-
It would be fine, as far as the internal data is integer type to keep the precision.
-
Sounds good, although I'd tend to return a const reference to a Time member inside Clock (not sure about Time's structure).
A time is an integer value, nothing more. But let's focus on the API please, not the details ;)
What are the function calls after the class definition for? I'm a bit confused there.
They construct time values. sf::Time has no constructor other than the default one, one must use one of these three functions.
It would be fine, as far as the internal data is integer type to keep the precision.
Internally it is of course a Int64 number of microseconds.
-
Looks fine to me :)
-
So here is a proposal for a new time API, that is a little more verbose than before but should make everyone happy.
It's almost certain that some people will not like it. You know, "omfg what u done its not simple anymore" ;)
As my opinion goes, it's okay.
-
Yeah, I knew this would come. Totally endorsed.
-
This is very similar to how I implemented time in rimfrost engine. But we also have hierarchy timers. Though think that is over kill here.
Anyway you have my thumbs upp.
-
"omfg what u done its not simple anymore"
-
It seems nice for me.
This way SFML still keeps satisfaying all of its users :D
-
I don't see any pause? :- (
And a interval with a callback like C# timers would be nice, but I guess I could just convert my old class.
-
Internally it is of course a Int64 number of microseconds.
Okay does that really remove the issue?
I mean you handle time still as Int64 which has the problem that you get 0 for all the function calls in between 0 and 1ms.
Which means that if I had a game loop that executes faster than 1ms I still would have to deal with the problem of 0.
Example: If I add every iteration the float of the passed time I'll constantly add 0+0+0+0+0, maybe occasionally get an 0.000001 in there but looking at my variable it would seem as if time has stopped.
Sure it can be fixed with always forcing to add a least 0.000001 and then sync it from time to time with the exact int and who ever needs performance below 1ms?
Just saying it doesn't fix all the issues...
-
Looks good to me.
Internally it is of course a Int64 number of microseconds.
Okay does that really remove the issue?
I mean you handle time still as Int64 which has the problem that you get 0 for all the function calls in between 0 and 1ms.
Which means that if I had a game loop that executes faster than 1ms I still would have to deal with the problem of 0.
Example: If I add every iteration the float of the passed time I'll constantly add 0+0+0+0+0, maybe occasionally get an 0.000001 in there but looking at my variable it would seem as if time has stopped.
Sure it can be fixed with always forcing to add a least 0.000001 and then sync it from time to time with the exact int and who ever needs performance below 1ms?
Just saying it doesn't fix all the issues...
Looks like he would be storing microseconds in that int64, not milliseconds.
-
Seems to be a good solution. And whoever thinks it's not simple anymore... wtf? ;-)
-
I don't see any pause? :- (
Pause() in the Time class ? I wouldn't make any sense. As Laurent said :
sf::Time would be a time span
BTW : looks good!
-
The new time API looks nice :)
Pause() in the Time class ? I wouldn't make any sense.
He probably meant Pause() in the sf::Clock class. But then Laurent would put me out of work :P
-
What are the function calls after the class definition for? I'm a bit confused there.
They construct time values. sf::Time has no constructor other than the default one, one must use one of these three functions.
Are they meant to be classless or is that just in that "mockup"? I'd prefer seeing them as static members in Time with "From" as prefix (similar to "To...").
-
Are they meant to be classless or is that just in that "mockup"? I'd prefer seeing them as static members in Time with "From" as prefix (similar to "To...").
The example is pretty explicit about their usage: they are free functions, yes.
Your solution would be definitely too verbose. And having similar functions but some as static and others as non-static, could be confusing.
I don't see any pause? :- (
sf::Clock is just provided for convenience, since the most common use case for time handling is measuring the elapsed time. It's not meant to provide fancy features. I could even remove this class and replace it with a sf::Time::Now() function -- but that would be slightly less "simple" ;)
-
Hm... I consider that pretty much standard and widely used (esp. in the .net and probably java world). It would be just a bit more sorted (having them not just sitting in the namespace).
Edit: Something like this would still look odd to me:
sf::Time &lastUse = sf::Second(someUnixTimeStampInt);
While this looks more obvious?
sf::Time &lastUse = sf::Time::FromSeconds(someUnixTimeStampInt);
-
Hm... I consider that pretty much standard and widely used (esp. in the .net and probably java world)
These languages don't support non-member functions... So it's not "standard and widely used", it's just the only solution ;)
It would be just a bit more sorted
It's in the same header and doc page as sf::Time. How could it be more sorted? ;)
-
new time api looks nice to me :)
-
About the pause() function : this is a real-time-passed clock system, not a virtual-time. That is good because now you can implement a virtual-time clock system specific to your game that would rely on the real-time clock.
I've done it before, it's easy to get right and you can even implement getting back in time if needed.
-
Looks very nice, Laurent.
I would drop the "To" though, as it indicates a conversion, which may not always be the case. Besides, for simplicity, the user shouldn't have to care about such details.
-
Looks very nice, Laurent.
I would drop the "To" though, as it indicates a conversion, which may not always be the case. Besides, for simplicity, the user shouldn't have to care about such details.
Agreed, "As" would be a better convention I think because it instead implies that you view something in another way instead of converting to. Though I guess that's my preference. You could do it without having a prefix as well.
Time time = /* Foobar */
time.AsSeconds();
time.AsMilliSeconds();
time.AsMicroSeconds();
It gives a cleaner readability too I think because it's more natural. You don't say "Time to seconds" you say "Time as seconds"
-
Hmm, "As" sounds good yes.
I won't drop the prefix, because it makes it clear that the function returns the whole time value, not the seconds/milliseconds/microseconds part of it.
-
Hm... I consider that pretty much standard and widely used (esp. in the .net and probably java world). It would be just a bit more sorted (having them not just sitting in the namespace).
I think global functions are perfectly fine for this. In C++, we fortunately don't have to put everything in classes ;)
Edit: Something like this would still look odd to me:
sf::Time &lastUse = sf::Second(someUnixTimeStampInt);
Same to me. No wonder with a reference to a temporary :D
Hmm, "As" sounds good yes.
I also like it. But are there other similar functions in SFML that begin with "To"? Or maybe a future sf::Time::ToStdDuration() interacting with Chrono?
-
But are there other similar functions in SFML that begin with "To"?
"To" functions usually apply to small utility classes that can be converted to another type, and SFML has very few of them. As far as I remember, there are "To" functions only in sf::String and sf::Utf.
Or maybe a future sf::Time::ToStdDuration() interacting with Chrono?
If I add such a conversion in the future, it will most likely be implicit. Since the type std::duration holds the semantic ("it's a duration"), unlike sf::Int32 which doesn't make it clear that you'll get milliseconds, there's no need have an explicit conversion function.
std::duration<...> d = clock.GetElapsedTime();
...looks good enough to me.
Same for the other way round:
sf::Sleep(std::seconds(1));
-
Your solution would be definitely too verbose.
Well, I'd rather give the functions verbose names than unclear ones. "Seconds"? What does it do with seconds? Ah, let's see in the docs... it returns a Time object that represents given amount of seconds. Okay. But "Time::FromSeconds" (or "TimeFromSeconds" or anything that explicitly states what the function does) makes that clear from the beginning.
And while it may seem consistent with the standard library, it's actually not. You see, std::seconds is a type that stores some duration in seconds, so it's pretty obvious name for it. It's not a named constructor.
-
Free functions are less clear the very first time you see them, while static member functions are confusing everytime you deal with a sf::Time instance (FromSeconds is static, ToSeconds is not -- the kind of thing that you never remember). I even expect users to post messages on the forum to ask why time.FromSeconds(n) doesn't modify their time variable.
And static functions are still very verbose. Making functions clear is the top priority, but there's a limit at which verbosity becomes important too.
And while it may seem consistent with the standard library, it's actually not. You see, std::seconds is a type that stores some duration in seconds, so it's pretty obvious name for it. It's not a named constructor.
std::seconds won't be better if the function that you're calling expects a template std::duration argument, or another specialized time class. Which might happen quite often.
-
Free functions are less clear the very first time you see them, while static member functions are confusing everytime you deal with a sf::Time instance (FromSeconds is static, ToSeconds is not -- the kind of thing that you never remember). I even expect users to post messages on the forum to ask why time.FromSeconds(n) doesn't modify their time variable.
You missed the point. I don't care whether it's static or not. It's all about the very name:
But "Time::FromSeconds" (or "TimeFromSeconds" or anything that explicitly states what the function does) makes that clear from the beginning.
std::seconds won't be better if the function that you're calling expects a template std::duration argument, or another specialized time class
Er, what do you mean?
-
You missed the point. I don't care whether it's static or not. It's all about the very name
Ok, I get it now.
But, seriously, what could sf::Seconds(n) return, other than a time value of n seconds? In actual code, the context will make it even more obvious. Seconds are time, it's implicit. "TimeFromSeconds" even looks weird, because seconds are already time. If sf::Seconds returned something else than a time value, ok, it would be very confusing. But it doesn't.
So do we really need all this extra verbosity? I don't think so.
Er, what do you mean?
You said that the STL API was clearer because std::seconds is a class. It's true: if the function that you're calling expects a std::seconds argument, it's clear that you must construct a std::seconds instance. But if it expects a std::duration<...>, a std::milliseconds or whatever other than std::seconds (which is likely to happen), then it's not clearer than SFML's solution, you still need to read the documentation to figure out what to do.
-
But, seriously, what could sf::Seconds(n) return, other than a time value of n seconds?
In fact, I have a hard time getting its meaning. I can't think of any thing that call could do. Including returning a time of n seconds. It's just too imprecise.
Seconds are time, it's implicit. "TimeFromSeconds" even looks weird, because seconds are already time.
That's disputable, actually. The definition of time is very abstract and vague. The definition of second is very precise. You know, the second is a unit of measurement of time (defined to, well, something). So, you have a number of seconds (a specific thing), and convert it to some abstract thing (namely, to time). Makes some sense, given that the end user isn't supposed to know how the time is defined internally (just like we don't how the universe represents the time internally) ;)
You said that the STL API was clearer because std::seconds is a class. It's true: if the function that you're calling expects a std::seconds argument, it's clear that you must construct a std::seconds instance. But if it expects a std::duration<...>, a std::milliseconds or whatever other than std::seconds (which is likely to happen), then it's not clearer than SFML's solution, you still need to read the documentation to figure out what to do.
The first thing one would try is probably to construct a std::seconds object and let the compiler worry about the (implicit) conversion. And this really works. But I don't see what does it have to do with what we're talking about. Its name is clearer because it's a class; the fact that it's in fact a typedef to a template has some nasty implications, that's right, but these are beyond the scope of what we're currently focusing on.
As an aside, a minor nitpick that's not meant to be treated very seriously (it just shows how relative things that we think are obvious can be): what's the result of "an hour + two minutes"? Sixty-two minutes? Why not fifty-eight minutes? In some cultures, the past is in front of you (because you can see it) and the future is behind you (because you can't). And you add, so you go forward, so you effectively subtract the time ;)
-
In fact, I have a hard time getting its meaning. I can't think of any thing that call could do. Including returning a time of n seconds. It's just too imprecise.
If you think of it as a named constructor for a time class (whether it is named sf::Seconds of sf::Time doesn't really matter), I think it's clear enough. It's not a function that does something.
That's disputable, actually. The definition of time is very abstract and vague. The definition of second is very precise. You know, the second is a unit of measurement of time (defined to, well, something). So, you have a number of seconds (a specific thing), and convert it to some abstract thing (namely, to time). Makes some sense, given that the end user isn't supposed to know how the time is defined internally (just like we don't how the universe represents the time internally)
You want a certain amount of seconds -> you call sf::Seconds. I think it's really straightforward. Adding "Time" to the function name would add confusion. At least that's my opinion and I'm not convinced by your arguments so far ;)
The first thing one would try is probably to construct a std::seconds object and let the compiler worry about the (implicit) conversion.
How does the user know about the std::seconds class if it doesn't appear in the function prototype?
But I don't see what does it have to do with what we're talking about.
You said that SFML tries to mimic the STL in a bad (or less clear) way. I think it's wrong, the same issues apply with the STL API.
As an aside, a minor nitpick that's not meant to be treated very seriously (it just shows how relative things that we think are obvious can be): what's the result of "an hour + two minutes"? Sixty-two minutes? Why not fifty-eight minutes? In some cultures, the past is in front of you (because you can see it) and the future is behind you (because you can't). And you add, so you go forward, so you effectively subtract the time
I think it's simpler than what you think: if you add two values of a certain unit, you must use mathematical addition. And you end up with a new value of the same unit which is the sum of both operands.
If I understand correctly, your point would apply if we tried to add a time span to a time point (like "what's the result of 11:52 plus 2 minutes?). But here we add a time span to another time span -- we get a bigger time span.
-
I think I know what Silvah is trying to point out (correct me if I'm wrong):
A "time" could be several things. It could mean a duration as well as a specific point in time (as in 5:00 pm). That's more or less ambiguous.
What I'd be doing would be calling the basic time object Duration and then renaming Clock to Stopwatch.
---
Actually, thinking about it, it could get even more interesting and making the rework even more awesome:
sf::Duration: Defines a specific duration like 5 seconds, 10 minutes or 50 µs.
sf::Clock: Abstract base class for the following classes (not sure about this one).
sf::Stopwatch: Essentially the current sf::Clock class. It allows you to start a timer and then determine the amount of time that has passed.
sf::Timer: A class allowing you to start a timer that will trigger a new event once some specific time has passed. The event data includes a pointer (or reference?) to this object, allowing identification/control. I'm not really sure how this should work, to be honest, it might as well be some extension to windows instead (window.SetTimeout(myidentifier,somedurationobject)).
-
A "time" could be several things. It could mean a duration as well as a specific point in time (as in 5:00 pm). That's more or less ambiguous.
There's absolutely no concept of time point in SFML, so the ambiguity is very reduced.
What I'd be doing would be calling the basic time object Duration
I have no strong argument against it, but sf::Time looks better :D
and then renaming Clock to Stopwatch.
I recently learnt that StopWatch is a better name, but it seems that sf::Clock is ok too.
sf::Clock: Abstract base class for the following classes (not sure about this one).
An abstract class here? Why?
sf::Timer: A class allowing you to start a timer that will trigger a new event once some specific time has passed.
SFML doesn't support "events" (signals/slots). And it's too high level anyway, what we're talking about is a simple (and thus unique) way of measuring and handling time.
-
It's not a function that does something.
But it is a function that does something, it returns an object ;)
You want a certain amount of seconds -> you call sf::Seconds. I think it's really straightforward.
I think it's not, the name is too vague. But I guess I have said that already.
Adding "Time" to the function name would add confusion. At least that's my opinion and I'm not convinced by your arguments so far ;)
Have I already said that you missed the point, by any chance?
But "Time::FromSeconds" (or "TimeFromSeconds" or anything that explicitly states what the function does) makes that clear from the beginning.
While I agree that the names I proposed aren't the most fortunate ones, they're not the only possibilities. Hopefully someone who knows English better than I do can come up with something better. So maybe we should focus on inventing better name instead?
How does the user know about the std::seconds class if it doesn't appear in the function prototype?
The user knows because it's the thing that one uses to store seconds. And then the user tries to pass it into something which expects other units. And lo! it happens to work. Hooray for trial and error! ;)
You said that SFML tries to mimic the STL in a bad (or less clear) way. I think it's wrong, the same issues apply with the STL API.
These issues are not the same. They're related, yes, but they're slightly different and their causes have nothing to do with each other.
-
Hmm... let's try to work differently ;)
Who else has an opinion about the function names? Clear and concise, or too vague?
Who (native english speakers?) can suggest better names?
You'd better answer if you want to see SFML 2.0 soon :twisted: :lol:
-
Who else has an opinion about the function names? Clear and concise, or too vague?
I think he has a point... Not a very strong one, but a point that counts towards the simplicity of trial and error...
You write sf::Time and hit the completion shortcut of your IDE: you get sf::TimeFromSeconds, sf::TimeFromMilliseconds and sf::TimeFromMicroseconds on the sugestion list.
But I wouldn't mind if it ends as you made so far.
-
For what it is worth, here's my ideas.
First, it was proposed to change sf::Clock name (to StopWatch or something else). IMHO, I think it is NOT a good idea : sf::Clock came in SFML 1 and changing its name for something "only a little bit better" would confuse most people. There won't be any benefit.
Now, about the sf::Time class : I would suggest sf::TimeSpan instead. It's maybe not the most crucial thing here. However, these 4 last letters clearly state that you won't be able to get the current day or the week, or get the next leap year, etc...
There is also the problem of ToSeconds(), or, as proposed above, AsSeconds(). Personally, I would prefer TotalSeconds instead because there's no meaning of conversion : we only extract the number of seconds from the time span. In fact, this is how Microsoft does it in C# with TimeSpan (http://msdn.microsoft.com/en-us/library/system.timespan_properties.aspx).
You discussed about making Seconds(), Milliseconds(), and Microseconds() static functions of sf::Time or free function instead. Because I have relatively little experience on this topic I decided to look around what was the best and found this article (http://drdobbs.com/184401197) :
[...]
This analysis applies to any kind of member functions, including static ones. Adding a static member function to a class when its functionality could be implemented as a non-friend non-member decreases encapsulation by exactly the same amount as does adding a non-static member function. One implication of this is that it's generally a bad idea to move a free function into a class as a static member just to show that it's related to the class. [...]
However, I 'm not sure what name fit the best. sf::TimeFromSeconds (or TimeSpanFronSeconds) is long but has no ambiguity and is straightforward. But Seconds seems enough in most context : like sf::Sleep(sf::Seconds(1)).
Sorry if I'm not focused on the real issue.
-
You'd better answer if you want to see SFML 2.0 soon :twisted: :lol:
Damn you!
I can understand his point. But I feel your arguments are more correct. Kind of hard to speak my mind from the phone. But take it as a base that I will always like the solution that makes it sound more like speech. Take time.As* for example.
I hope I count as well since I started with English around the age of 8.
EXPANSION:
Alright now that I'm on my Laptop instead I would like to expand this a little more.
From my understanding this is the proposed convention from Silvah:
time = sf::Time::FromSeconds(N);
This to me reads as: "time equal to time from N seconds"
Could cut away the second time but it still become "time equal to from N seconds"
This is why I like Laurents version more as it becomes:
time = sf::Seconds(N);
which in my eyes reads as "time equal to N seconds". And to me this feels a lot more natural.
And I can't see the ambiguity that other's see with having these functions in the global space. But since people are seeing things. It means that it isn't perfect. But I urge that you do something similar. I really love it when you can read the code as normal English speech and it goes hand in hand with readability, some programming paradigms like polymorphism and in some cases it can also solve ambiguity just as how it is solved in real life language. Though of course sometimes you can still be confused in real life because you missed the context as the sentence was said in. But doing that in code is much harder in my opinion because the text is there starring you in the face while words float away and you have to guess what you missed.
Just adding an example and "translating it":
sf::Time time = sf::Seconds( N ); // time is equal to N seconds
printf( "%f", time.AsMicroSeconds() ); // Print the time as micro seconds
myCountDown -= clock.GetElapsedTime(); // The countdown is subtracted with the elapsed time.
if( myCountDown <= sf::Seconds( 0 ) ) // If the countdown is less or equal to 0 seconds then do stuff
doStuff();
-
I really like "AsSeconds", as Groogy suggested. It's short, and it explains what it does perfectly.
"TotalSeconds" is not only longer, but it also introduces ambiguity, as it could be understood as "the seconds component of the time duration".
I also see Silvah's point. TimeFromSeconds is self-explanatory, while Seconds is not. It is also a long name, but is that really such a big problem in this case? Is it likely to often be used in a context where the long name makes the code hard to read?
Also, I think I would personally find TimeFromSeconds easier to remember, because it starts with Time. I often have a hard time remembering names, so code completion helps me a lot.
-
So much discussion... for a little innocent name.. :(
-
You are right, it probably isn't that important, but Laurent is holding SFML 2.0 hostage! :( :wink:
-
if( myCountDown <= sf::Seconds( 0 ) ) // If the countdown is less or equal to 0 seconds then do stuff
doStuff();
Not that it matters much, but I don't think this would work as I think you wanted it to... It would only check if the myCountDown clock haven't yet passed one single microsecond, as the time instance with 1 microsecond is bigger than the one with 0.
-
Not that it matters much, but I don't think this would work as I think you wanted it to... It would only check if the myCountDown clock haven't yet passed one single microsecond, as the time instance with 1 microsecond is bigger than the one with 0.
As the name and comment imply, I think the myCountDown variable decreases until it reaches zero. So the code is ok.
-
Well, am I not dumb? :lol:
I've read each line of the code separately.
-
Also functioning code wasn't my point but the fact that you can read the code as normal English. Ruby is based on this concept. Example:
10.times do
print "Hello World!"
end
Reading that becomes "10 times print hello world!" or even "10 times do action print hello world!" (If you take to note that the do-notation in Ruby is a lambda function)
As soon as you add more text to a name to "reduce ambiguity", reading it becomes harder. Now of course not everyone might approve of how I do it to solve ambiguity and increase readability. But since SFML is supposed to be simple I think having it close to English speech makes it that by default. As having the code written as this forces the user to maintain it simple, readable and the context in the code can be derived from the surrounding code just like in a book.
-
From my understanding this is the proposed convention from Silvah:
time = sf::Time::FromSeconds(N);
I wasn't the one who proposed this. Mario was (http://sfml-dev.org/forum/viewtopic.php?p=44504#44504).
So much discussion... for a little innocent name.. :(
No wonder, naming is the hardest thing in programming :D
-
While I agree that function names should be intuitive, I wouldn't exaggerate. Long names are more difficult to read, write and remember; in my opinion they are only worth the drawbacks when they really increase the expressivity.
And I think that
sf::Time time = sf::Seconds(4);
is perfectly expressive, as well as
sf::Sleep(sf::Seconds(4));
On the other side, things like
sf::Time t = sf::Time::FromSeconds(4);
or
sf::Sleep(sf::Time::FromSeconds(4))
are heavy and contain duplicate information, but don't give us more information about the semantics. At least no useful one -- we see that a sf::Time object is constructed, but since sf::Time is the only SFML time class, this is obvious. Additionally, the exactly returned type isn't that important.
Also concerning sf::TimeSpan: While it is useful to differ between time points and time spans (like duration in Boost/Std), SFML doesn't have this concept, so I consider sf::Time general enough.
-
I've pushed the new API. I didn't change anything, except the prefix: "To" is now "As".
-
I've pushed the new API. I didn't change anything, except the prefix: "To" is now "As".
My work here is done 8)
-
As it's no longer possible to just use "sf::Sleep(0);" to allow context switches (or I missed something new other than calling "sf::Sleep(sf::Seconds(0));"?), how about adding something like "sf::Idle();" or "sf::Sleep(sf::Idle);" just doing that? Just a bit lazy here.
-
There's a special Time::Zero value
sf::Sleep(sf::Time::Zero);
Is that enough?
If I implemented an "Idle" thing it would have to be specialized according to the OS, Sleep(0) is not strictly equivalent. And by the way, it would probably be named sf::Yield().
-
Sounds reasonable enough.
-
I've pushed the new API. I didn't change anything, except the prefix: "To" is now "As".
Sounds great, I'm looking forward to update and adapt everything in Thor :)
(really)
-
What do you think about an operator that returns the ratio between two times?
float operator/ (sf::Time lhs, sf::Time rhs)
{
return lhs.AsSeconds() / rhs.AsSeconds();
}
By the way, why don't you pass sf::Time objects by value? You do it also for sf::Uint64. 8 bytes to copy is negligible, considering that references usually consume also 4 or 8 bytes. However, pass by value doesn't imply the dereferencing cost, and code becomes more beautiful without const&. In the end, you can only win :)
-
What do you think about an operator that returns the ratio between two times?
What would it mean?
By the way, why don't you pass sf::Time objects by value?
I have no idea, I already do it for all other functions :lol:
-
What would it mean?
Generally, the operator/ can be used to find out what fraction of a time span has already passed. A concrete use case looks like this:
// Returns particle lifetime progress in [0, 1]
float GetPassedRatio(const Particle& particle)
{
return GetPassedLifetime(particle) / GetTotalLifetime(particle);
}
I have no idea, I already do it for all other functions :lol:
A search&replace is performed fast :D
-
Generally, the operator/ can be used to find out what fraction of a time span has already passed.
Ok. But what if one wants an integer division? Isn't it better to let users choose what type they want to manipulate for this specific use case?
A search&replace is performed fast
Yep, I'll do it.
-
I thought this operation will be natural from a mathematical point of view, if we are able to multiply times with factors.
time1 == factor * time2
time1 / time2 == factor
However I see that there is a problem because there are operator* overloads for float and sf::Uint64...
I'm not sure whether two overloads are a good idea anyway, since it makes multiplications ambiguous for other factor types. But I also understand that providing only sf::Uint64 is too unflexible, and only float might lead to loss of precision...
In Boost.Chrono, the division of two duration<T> objects yields T as return type. Hmm, tricky :?
-
I think leaving it to the user is better because there is only headache along this path. If you really want it I wouldn't do it as an operator as it's return type is not the same.