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

Author Topic: Ostream operators << for SFML classes  (Read 8060 times)

0 Members and 1 Guest are viewing this topic.

Kojay

  • Full Member
  • ***
  • Posts: 104
    • View Profile
Ostream operators << for SFML classes
« on: March 19, 2014, 04:51:38 pm »
I propose that SFML provides ostream operators for its classes to make for easier debugging (like Qt does - but not necessarily all the features of qDebug).

The chief design question in my view is whether those should be provided in a single header or along with each class. The ones for Vector and Rect would be presumably templated and have to be in a header, while the rest could be implemented in the source files.

Aster

  • Full Member
  • ***
  • Posts: 130
    • View Profile
Re: Ostream operators << for SFML classes
« Reply #1 on: March 19, 2014, 05:00:34 pm »
I fully support this thought. It's definitely a good idea to have ostream operators for SFML classes, as they would not only make debugging easier, but they would make code prettier as well.

The real question is -- How do we output the classes?
And, would it not be better to have string operators instead? That would also make it possible to send the classes over network. Although I suppose the verbosity you want from a string operator is not the same as that of an ostream/debug code.

All in all, this is a really good suggestion, and I vote yay.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Ostream operators << for SFML classes
« Reply #2 on: March 19, 2014, 05:37:32 pm »
I don't think this is possible to do. Serializing something to a stream means to choose a format. And there's not a single good solution to this choice. Should we just serialize members directly so that we can use it to output stuff to binary files or network? Or should we do some pretty formatting for debugging purpose? This choice is up to the user, I don't see how I can provide a generic solution in SFML. By the way, if you write  operators << you have to provide operators >> as well, and things are even worse with them (parsing is a lot more complex than printing) ;)
Laurent Gomila - SFML developer

Aster

  • Full Member
  • ***
  • Posts: 130
    • View Profile
Re: Ostream operators << for SFML classes
« Reply #3 on: March 19, 2014, 05:54:02 pm »
Maybe it might be a good feature to add, for once, especially since SFML's behavior can be quite unexpected; giving its users something to easily debug with could be a good idea.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Ostream operators << for SFML classes
« Reply #4 on: March 19, 2014, 05:58:26 pm »
Maybe it might be a good feature to add
What about the points Laurent mentioned?

especially since SFML's behavior can be quite unexpected
What do you mean? In my opinion, SFML is one of the most intuitive C++ libraries...
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

dabbertorres

  • Hero Member
  • *****
  • Posts: 506
    • View Profile
    • website/blog
Re: Ostream operators << for SFML classes
« Reply #5 on: March 19, 2014, 06:05:02 pm »
SFML already offers lots of ways to let you know if something failed (see all the loadFrom* functions). It just leaves it up to the programmer to take advantage of that, and I don't see that as a problem. It's relatively simple to debug then. If you want some sort of logger class, here's an example.

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: Ostream operators << for SFML classes
« Reply #6 on: March 19, 2014, 06:08:57 pm »
... especially since SFML's behavior can be quite unexpected; giving its users something to easily debug with could be a good idea.

Ehh, examples please.
Personally I find SFML to be one of the most unsurprising, well designed, easy to work with/debug C++ libraries that I have ever worked with. I'm genuinely currious about what you find so "unexpected"??

Aster

  • Full Member
  • ***
  • Posts: 130
    • View Profile
Re: Ostream operators << for SFML classes
« Reply #7 on: March 19, 2014, 06:10:26 pm »
Maybe it might be a good feature to add
What about the points Laurent mentioned?

<< doesn't require >>.
Basically every single feature request is "outside of SFML's scope".
Choosing a format isn't difficult, just pick some JSON-esque thing, or anything Human-readable. It's debug.
I agree that the choice between "creating debug output" and "turning a class into a string for multiple uses" is difficult, but come on, this is a fully-fledged library, don't tell me you can't make simple decisions.

especially since SFML's behavior can be quite unexpected
What do you mean? In my opinion, SFML is one of the most intuitive C++ libraries...
Sure, SFML is intuitive etc. But there are some really stupid bugs that get out, with every release, that can easily be fixed with any kind of testing, and I stopped using SFML because I'm tired of having to debug my code out of worry that SFML itself might have the problem, and not my codebase. An ostream<< operator might make debugging SFML code much easier.

Plus, SFML is made to be simple and fast, so why should the user have to write a ton of debug code? That's not quick development.

I understand that SFML takes a lot of effort to maintain etc, but there are simple features like clipboard support and whatnot that competing libraries have, and SFML stays too stubborn to implement.
« Last Edit: March 19, 2014, 06:20:48 pm by Aster »

Aster

  • Full Member
  • ***
  • Posts: 130
    • View Profile
Re: Ostream operators << for SFML classes
« Reply #8 on: March 19, 2014, 06:19:37 pm »
Ehh, examples please.
Personally I find SFML to be one of the most unsurprising, well designed, easy to work with/debug C++ libraries that I have ever worked with. I'm genuinely currious about what you find so "unexpected"??

SFML doesn't work on Linux with Xinerama.

SFML 2.0 got released with a very annoying bug where the window wouldn't get "selected" if you clicked the mouse inside of it. It drove me crazy, and I probably spent hours trying to find out what was going on, thinking my code was the one responsible.
It also had some bug with reporting window position on Linux. Another quite bothersome bug for me to work with at the time.

SFML 2.1 released with several other bugs.

There are tons of forgotten (and unfixed) bugs on the issue tracker.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Ostream operators << for SFML classes
« Reply #9 on: March 19, 2014, 06:28:07 pm »
<< doesn't require >>
It feels unintuitive if there's no counterpart. When overloading operators, you should go for the principle of least surprise ("do as the ints do"); that's a commonly accepted convention in C++. Otherwise, named functions are often better suited.

Basically every single feature request is "outside of SFML's scope".
Have a look at the feature list on GitHub (both open and closed). Tons of features have been and will be implemented. Of course, there are also features being rejected, mostly because people only have a very specific use case in mind and don't think of the design implications of "just add this, it may be useful". But we just discussed this recently, and I'd like to stay on topic here ;)

Choosing a format isn't difficult, just pick some JSON-esque thing, or anything Human-readable. It's debug.
You say it's for debug and expect verbose output. Others want vectors to be displayed as (x,y) in a map editor. There are far too many different use cases of string output, especially for the more complex SFML classes.

An ostream<< operator might make debugging SFML code much easier.
So the purpose is debugging SFML and not your own code? Then I don't know how that feature would help anyway, since it would output the public API and not the implementation. To debug SFML, you should use an actual debugger. It's more powerful in general, and you can inspect a lot of things that code cannot.

Plus, SFML is made to be simple and fast, so why should the user have to write [...]
You can say that about every possible feature.

There are tons of forgotten (and unfixed) bugs on the issue tracker.
You could help investigate them. A lot of bugs have been fixed as a result of contributions from the community.
« Last Edit: March 19, 2014, 06:53:43 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Aster

  • Full Member
  • ***
  • Posts: 130
    • View Profile
Re: Ostream operators << for SFML classes
« Reply #10 on: March 19, 2014, 07:00:01 pm »
Alright, I'm not going to quote everything, but..
I agree on the unintuitiveness of << with no >>.

The features added in SFML from GitHub often don't add anything major. (This is where you link me a single major feature as proof that I'm lying.)

SFML has sf::NonCopyable, why not make sf::Printable or similar?

And no, the purpose of the ostream<< operator is obviously not to debug SFML. I said it might make it easier.

Also, if I had the expertise required to fix some of those bugs, I would. But I don't, hence why I use something high-level such as SFML.

dabbertorres

  • Hero Member
  • *****
  • Posts: 506
    • View Profile
    • website/blog
Re: Ostream operators << for SFML classes
« Reply #11 on: March 19, 2014, 07:00:32 pm »

Kojay

  • Full Member
  • ***
  • Posts: 104
    • View Profile
Re: Ostream operators << for SFML classes
« Reply #12 on: March 19, 2014, 07:08:09 pm »
I don't think this is possible to do. Serializing something to a stream means to choose a format. And there's not a single good solution to this choice. Should we just serialize members directly so that we can use it to output stuff to binary files or network? Or should we do some pretty formatting for debugging purpose?

My proposal concerns the latter - pretty output for debugging purposes. The choice issue can be tackled by mimicking Qt; that is a sfDebug() class (albeit lighter than qDebug) that can be used similarly to a std::ostream and will not interfere with the operators written by the user. This can also be automatically left out of release builds, as well as allow the user to easily redirect the output.

Quote
By the way, if you write  operators << you have to provide operators >> as well, and things are even worse with them (parsing is a lot more complex than printing)

Quote
t feels unintuitive if there's no counterpart. When overloading operators, you should go for the principle of least surprise ("do as the ints do"); that's a commonly accepted convention in C++. Otherwise, named functions are often better suited.

I 'm not aware of this convention applying to these operators; surely input and output are distinct enough that once can conceive meaning for one but not the other.

To be clear, I think SFML is very intuitive to use and believe providing pretty output for its classes to be in this spirit.

So that we 're not talking about thin air, I will post an example of this sfDebug() class later.

Austin J

  • Newbie
  • *
  • Posts: 29
    • View Profile
    • Email
Re: Ostream operators << for SFML classes
« Reply #13 on: March 20, 2014, 04:36:57 am »
  I don't believe that libraries should serialize their objects for you in vast majority of cases. I don't know maybe serializing simple things like sf::Vector2 would be ok, but why on earth would someone ever want to save a whole sprite, or even worse a texture directly to a file?

Kojay

  • Full Member
  • ***
  • Posts: 104
    • View Profile
Re: Ostream operators << for SFML classes
« Reply #14 on: March 20, 2014, 09:33:45 am »
Without further ado:

namespace sf {

class Debug {
public:

    Debug (std::ostream& sink = std::cout):
        m_stream(sink)
    {

    }    

    template <typename T>
    Debug& operator<<(const sf::Vector2<T>& vector) {
        m_stream << "Vector(" << vector.x << ", " << vector.y << ")\n";
        return *this;
    }

    template <typename T>
    Debug& operator<<(const sf::Rect<T>& rect) {
        m_stream << "Rect(" << rect.left << ", " << rect.top << ", " << rect.width << ", " << rect.height << ")\n";
        return *this;
    }

    Debug& operator<<(const sf::Transform& transform) {
        const float* matrix = transform.getMatrix();
        m_stream << "Transform:\n";
        for (int i=0; i<4; ++i){
            m_stream << "( ";
            for (int j=0; j<4; ++j)
                m_stream << matrix[i*4 + j] << " ";
            m_stream << ")\n";
        }
        return *this;
    }

    Debug& operator<<(const sf::Sprite& sprite) {
        m_stream << "Sprite: ";
        operator<<(sprite.getGlobalBounds());
        return *this;
    }

    ~Debug() {
        m_stream.flush();
    }

private:
    std::ostream& m_stream;

};

Debug debug(std::ostream& sink = std::cout) {
    return Debug(sink);
}

}
 

(Four operators implemented for demonstration purposes)
Drawback: cannot be used to output built-in or non-sfml types

Example usage:

sf::debug() << sf::Vector2f(10, 10) << sf::Vector2f(20, 20); //output to cout by default

sf::Sprite sprite;
sf::debug(std::cerr) << sprite << sprite.getTransform(); //outputs to cerr
 

Output:
Code: [Select]
Vector(10, 10)
Vector(20, 20)
Sprite: Rect(0, 0, 0, 0)
Transform:
( 1 0 0 0 )
( -0 1 0 0 )
( 0 0 1 0 )
( 0 0 0 1 )

It's easy to have it output to a fstream or stringstream instead.
The ctor is public so the user can make a persistent Debug object if they wish.

Quote
why on earth would someone ever want to save a whole sprite, or even worse a texture directly to a file?

Not the point.