Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Change Unit of Measure  (Read 24020 times)

0 Members and 1 Guest are viewing this topic.

Klaim

  • Full Member
  • ***
  • Posts: 137
    • View Profile
Re: Change Unit of Measure
« Reply #15 on: July 11, 2013, 09:47:29 pm »
Since SFML 3.0 will probably have C++11 support, Laurent might want to try out making use of user defined literals in order to solve this problem ;). SFML would probably be one of the first libraries to make use of UDL, but you know it sounds too good to pass up :).

It don't solve the problem, it just add a shorter syntaxe. You still need some kind of type definitions to use inside the user-defined literals. But yeah that would be cool.

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Change Unit of Measure
« Reply #16 on: July 11, 2013, 10:09:54 pm »
What type definitions? The user-defined literal is converted to the appropriate angle type when being passed to any function that would take an angle. No type definitions there...
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Klaim

  • Full Member
  • ***
  • Posts: 137
    • View Profile
Re: Change Unit of Measure
« Reply #17 on: July 12, 2013, 12:29:40 am »
What type definitions? The user-defined literal is converted to the appropriate angle type when being passed to any function that would take an angle. No type definitions there...

How do you know the angle type? No, better: how does the compiler knows the angle types so that it can stop you when you're implicitely trying to convert?
The user-defined litterals just let you associate litteral shortcut syntaxes to types. So you first need these types.

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Change Unit of Measure
« Reply #18 on: July 12, 2013, 01:00:13 am »
Do you need to know the angle type? Not really... if you want to pass an angle in degrees, mark it with _deg, if you want radians then _rad. You don't need to rely on the implicit type if you don't want to. As an example, you could pass shorts around as 10_s if that makes it more clear you intend on it being interpreted as a short as opposed to an int or what not (this is really useful when trying to pack short literals into an sf::Packet without explicit casting). User-defined literals are not meant as a way to prevent errors by passing PODs around. If you wanted that, all functions would take some kind of an Angle type but since this topic was about being able to pass different units to functions without worrying about conversions, user-defined literals solves that problem completely.

User-defined literal is quite literally what the name implies, a mechanism for you do define your own kinds of literals. Literals aren't bound to a type until they are put into a certain context. That is why your literal handling function gets nothing but the string of characters straight out of your source code and it is up to you to interpret them in any way you want. You can make both _deg and _rad return some double value, be it in degrees, radians, gradian or whatever crazy unit you can think of. It just has to fit with the rest of the interface.

With great power comes great responsibility, and the possibility of more facepalms than you might expect. Maybe more facepalms than Laurent is willing to cope with :P.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Mario

  • SFML Team
  • Hero Member
  • *****
  • Posts: 879
    • View Profile
Re: Change Unit of Measure
« Reply #19 on: July 12, 2013, 09:51:19 am »
To me this could actually be something for a very simple class/struct like sf::Time. In the end you've got the same issue here: Several different units essentially measuring the same thing (and different functions obviously expecting different dimensions).

This would work on any platform. Using C++11 as an additional feature sounds neat, but at the same time you've still got the same issue in older standards.

Foaly

  • Sr. Member
  • ****
  • Posts: 453
    • View Profile
Re: Change Unit of Measure
« Reply #20 on: July 12, 2013, 10:05:20 am »
I have to agree. Unnessesary converting back and forth between degree and radians is a waste of time and performance. I have worked with ogre before and the way they implemented it is very nice and handy. But something similar to sf::Time would be great too.

AxelRantila

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Twitter
Re: Change Unit of Measure
« Reply #21 on: July 12, 2013, 04:43:33 pm »
But something similar to sf::Time would be great too.
I would like to see something like this as well.

Klaim

  • Full Member
  • ***
  • Posts: 137
    • View Profile
Re: Change Unit of Measure
« Reply #22 on: July 12, 2013, 09:23:04 pm »
@binary1248 I think you totally don't understand why you need types in this specific case. As other pointed, it's the same problem than with sf::Time values or std::chrono time values. You don't want implicit conversions. Using user defined literals without types (or by returning a basic type like float for example) is like asking for obscure ninja conversion errors to happen. If you don't understand this, maybe you didn't hit them enough yet. It's typically the kind of error that make space projects fails.

To me this could actually be something for a very simple class/struct like sf::Time. In the end you've got the same issue here: Several different units essentially measuring the same thing (and different functions obviously expecting different dimensions).

Exactly.
The point is that the same values with different referential MUST NOT be mixed without being converted to the same referential, whatever the way.


Quote
This would work on any platform. Using C++11 as an additional feature sounds neat, but at the same time you've still got the same issue in older standards.

You don't need C++11 to do it. User defined literals are basically allowing you to associate a litteral value to a type (with a potential conversion). It is not intended nor should be used as binary1248 described (which is actually a dangerous practice).

I have to agree. Unnessesary converting back and forth between degree and radians is a waste of time and performance. I have worked with ogre before and the way they implemented it is very nice and handy.
But something similar to sf::Time would be great too.

I prefer the typed way of Ogre::Radian/Degree personally as the compiler helps pointing potential errors instead of allowing you to mix with floats like in SFML. It also don't add any conversion until you use only a type different than SFML.
The approach used by Ogre::Radian/Degree is actually similar to std::chrono time values.
sf::Time is nice, but it does force you to convert the value to something at the point of use.


Jebbs

  • Sr. Member
  • ****
  • Posts: 358
  • DSFML Developer
    • View Profile
    • Email
Re: Change Unit of Measure
« Reply #23 on: July 12, 2013, 09:32:14 pm »
To me this could actually be something for a very simple class/struct like sf::Time.

I too think this is a great idea, mostly because it would solve this issue:

Unnessesary converting back and forth between degree and radians is a waste of time and performance.

Let's get an sf::Angle! Simple, yet so useful.
DSFML - SFML for the D Programming Language.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Change Unit of Measure
« Reply #24 on: July 12, 2013, 09:45:57 pm »
You should create a task on the tracker if you don't want me to forget this issue :P
Laurent Gomila - SFML developer

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Change Unit of Measure
« Reply #25 on: July 12, 2013, 09:58:15 pm »
sf::Time is nice, but it does force you to convert the value to something at the point of use.
The same applies to Degree and Radian classes, you have to call something like an asFloat() function as soon as you need to perform a computation with it. That is currently the biggest drawback of such wrappers, every trigonometric function call requires an explicit conversion. The only way to cope with this consists of overloading a large number of functions.


Let's get an sf::Angle! Simple, yet so useful.
I agree, for SFML this approach might be more meaningful than two separate types sf::Degree and sf::Radian. Basically, you are interested in storing an angle, not a specific format thereof. Additionally, sf::Angle would have an API consistent to sf::Time:
class Angle
{
public:
    float asRadians() const;
    float asDegrees() const;  
};

Angle radians(float angle);
Angle degrees(float angle);

... // arithmetic and relational operators


You should create a task on the tracker if you don't want me to forget this issue :P
Yes, let's first come to a conclusion in this thread, to avoid a parallel discussion on GitHub.

We should also agree on whether the additionally introduced complexity (mainly explicit conversion functions) is justified by the advantages.
« Last Edit: July 12, 2013, 10:18:07 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Jebbs

  • Sr. Member
  • ****
  • Posts: 358
  • DSFML Developer
    • View Profile
    • Email
Re: Change Unit of Measure
« Reply #26 on: July 12, 2013, 10:47:53 pm »
Do you think it would make more sense for asRadians() to return a double? I'd hate to have errors due to lack of precision on those.
DSFML - SFML for the D Programming Language.

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Change Unit of Measure
« Reply #27 on: July 12, 2013, 11:25:49 pm »
You still don't get why user-defined literals will help. Even with that Ogre system, you are passing dimensionless values to get converted to some angle object or to be interpreted in whatever way you specify. Does it prevent you from passing 90.0 to a function that takes an angle in radians? Not really, because you need to construct the radian angle using a value as well. If you use user-defined literals, you are forced to explicitly write the unit as part of the value you specify hence making it 100% clear you are passing an angle in the specified unit.

You might disable implicit conversion and force people to write stuff like .setAngle( Degrees( 90.0 ) ) but at what cost? You create a temporary just to make it look safer than it actually is? Someone might end up doing something stupid like .setAngle( Degrees( m_angle ) ) and set m_angle somewhere else, defeating the purpose of making it clear what the unit is. Yes... some programmers are really that dull. With user-defined literals, there is the possibility to use constexpr to make the compiler evaluate the value already at compile time thus eliminating any run-time overhead that might be incurred using temporaries.

If you aren't content with a user-defined literal just evaluating to a POD with known unit type because of those ninja conversion errors, then make it evaluate to an angle. And better still, make it impossible to construct such an angle in any other way than through a literal or any safe construction methods (like copying). That way, you force people not to be lazy and do things like .setAngle( Degrees( m_angle ) ).

Take sf::Time for example. Someone could write something like sf::sleep( sf::seconds( m_sleep_time ) ) in their main. In some other file at line 1337, they might set m_sleep_time to 1000. Do they realize that they have committed an error? No, because they were lazy, and nothing about sf::Time will prevent it from happening.

If, however, they had to construct the sf::Time using a user-defined literal every time, they wouldn't be allowed to do stupid things like that because they would need to set m_sleep_time to 1000_ms and call sf::sleep( m_sleep_time ) hence eliminating that error source.

I'm against adding extra classes/types just to prevent errors, especially since the language provides facilities that can make it impossible even for the most dull of programmers to make stupid mistakes. If there is a weak point in any solution you always have to count on it being its undoing. And to add insult to injury, you add potential runtime overhead as well.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
Re: Change Unit of Measure
« Reply #28 on: July 12, 2013, 11:56:51 pm »
I haven't yet tried those UDL but I have a question: do they work only on number literals or can they also work on floating point variables?

I.e., is the following code valid with the proper definition of _rad? (I guess it isn't..)

double deg = 180;
double rad = deg _rag;
 

If not, I think having a "true" type, like sf::Time with sf::seconds, would be good to, for example, load values from a file without involving complex serialization systems. Or any other scenario where the values are not hardcoded.

Any additional opinion on that?

EDIT: but having both might also have some upsides..
« Last Edit: July 13, 2013, 12:05:51 am by Hiura »
SFML / OS X developer

Silvah

  • Guest
Re: Change Unit of Measure
« Reply #29 on: July 13, 2013, 12:00:53 am »
And how exactly are user-defined literals supposed to help? You still can do sf::sleep(operator "" _s(time)); where time is the number of milliseconds. In fact, that ugly syntax what you have to do when the number is not a compile-time literal.

It's C++, it's virtually always possible to break all idiot-proofing if you try hard enough or are stupid enough.