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

Author Topic: sf::NonCopyable and =delete  (Read 32568 times)

0 Members and 1 Guest are viewing this topic.

Nexus

  • Moderator
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: sf::NonCopyable and =delete
« Reply #15 on: April 09, 2017, 11:16:06 am »
Maybe we should ask ourselves also what kind of move/copy semantics SFML will support, and how corresponding base classes would look. As we all know, C++ is much more gradual than copyable vs. non-copyable now.
  • Copyable and movable: The default, all lightweight classes but also certain resources (e.g. sf::Image). Ideally, we could use the Rule Of Zero here, but unfortunately this is not possible with using standard smart pointers alone. How are we going to implement them without boilerplate code? My library Aurora would offer a solution, other ideas?
  • Non-copyable, movable: Most if not all of the classes that have been non-copyable before would fall into this category. The main use case are heavy system resources such as windows.
  • Non-movable: There is no intrinsic reason why a class should be non-movable, as movability can always be achieved by introducing an indirection. And even without that, it would be more "movable without strong exception guarantee", e.g. for arrays where move implies copy. Do we have such classes?
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
Re: sf::NonCopyable and =delete
« Reply #16 on: April 12, 2017, 12:42:57 pm »
I like the current API design, where 'data' resources can be copied (e.g. Image) but 'system' resources cannot (e.g. Window), and I believe we have no classes falling in your third category, nor should we have some. Since you bring the question, do you think we should change something in that respect?
SFML / OS X developer

Nexus

  • Moderator
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: sf::NonCopyable and =delete
« Reply #17 on: April 12, 2017, 10:29:07 pm »
We should definitely make 'data' resources both copyable and movable, but that's planned anyway.

And as mentioned above, it would be good if we could avoid The Big Five whenever a class needs both copy and move semantics, but unfortunately this is not possible with standard tools alone (as soon as a class doesn't only have value members)...
« Last Edit: April 12, 2017, 10:30:41 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Ceylo

  • Hero Member
  • *****
  • Posts: 2325
    • View Profile
    • http://sfemovie.yalir.org/
    • Email
Re: sf::NonCopyable and =delete
« Reply #18 on: January 10, 2018, 10:44:47 pm »
To add my non-constructive ( ;D ) opinion to this old thread:

I'm for using what C++ natively provides because:
- creating sf::Copyable is reinventing the wheel, it's not because you disagree with the standard for what's best that you should do it your own way. A 10 pages argument to explain that it's shorter to read is not worth the benefit of using standard already known stuff.
- modern C++ developers will know these operators, and as years pass, more and more will be used to that standard rather than non_copyable class
- by doing it yourself you prevent yourself from using more subtle cases like: non-copyable & non-movable, movable but non-copyable, plus the possible noexcept specifier on these methods, and eventually the differences that can be introduced with deleting copy constructor but keeping  copy assignement operator available, even if it's probably an unneeded corner case in SFML's usage
- you may miss benefits from C++ evolutions that can make use of the deleted or available operators, which precisely define the allowed behavior, while a sf::NonCopyable would over-specify what's actually needed just because it'd need to be usable commonly in SFML.
« Last Edit: January 10, 2018, 10:46:55 pm by Ceylo »
Want to play movies in your SFML application? Check out sfeMovie!

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: sf::NonCopyable and =delete
« Reply #19 on: October 11, 2019, 04:57:17 pm »
Someone raised a concern on GitHub that the parent NonCopyable approach still allows for copying, if a copy constructor is explicitly implemented.

#include <iostream>
 
class noncopyable {
public:
        noncopyable() = default;
        noncopyable(const noncopyable&) = delete;
        noncopyable(noncopyable&&) = delete;
        void operator=(const noncopyable&) = delete;
        void operator=(noncopyable&&) = delete;
};
 
class foo : public noncopyable {
public:
        foo() = default;
        foo(const foo&)
        {
                puts("I'm copied!");
        }
};
 
int main() {
        foo f;
        foo f2(f);
        return 0;
}

https://ideone.com/yGp7SP
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: sf::NonCopyable and =delete
« Reply #20 on: October 12, 2019, 09:46:40 pm »
Is that a concern? sf::NonCopyable is just a shortcut/convenience to avoid defining all the stuff that makes a class non-copyable. It was never meant to enforce full non-copyability over all levels of derived classes.

If you inherit from a non-copyable class, but define a copy constructor because your derived class knows how to copy itself (without copying the base, obviously), then it's perfectly fine. I've done this many times with Qt and its non-copyable QObject base.
Laurent Gomila - SFML developer

markand

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
Re: sf::NonCopyable and =delete
« Reply #21 on: October 14, 2019, 03:28:30 pm »
IMHO, a parent class for removing/adding functionality in a subclass is not the good way to do. Especially as explained above. Class inheritance means "IS-A" not "HAS"/"HAS NOT".

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: sf::NonCopyable and =delete
« Reply #22 on: October 14, 2019, 08:43:40 pm »
Quote
Class inheritance means "IS-A" not "HAS"/"HAS NOT".
Public inheritance means "IS-A". Private inheritance, which is how sf::NonCopyable is meant to be used, is like composition (you inherit features, not a public interface), so it really is "HAS".
Laurent Gomila - SFML developer

nogoodname

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: sf::NonCopyable and =delete
« Reply #23 on: October 18, 2019, 04:20:25 pm »
Going to give my 2 cents on this old thread. IMO the concept of NonCopyable isn't as useful as it was in C++03, it now split into 2 concepts now: MoveOnly and NonMoveable.

I'll say that NonCopyable is kinda redundant giving that you can to the same thing with =delete.
E.g. Foo& operator=(Foo&&) = delete; will do the same thing as Foo inheriting from sf::NonCopyable in 1 line.
« Last Edit: October 18, 2019, 04:22:41 pm by nogoodname »

reconn

  • Newbie
  • *
  • Posts: 5
    • View Profile
    • Email
Re: sf::NonCopyable and =delete
« Reply #24 on: December 09, 2021, 02:52:33 am »
I believe sf::NonCopyable does more harm than good in the long run. Early/inexperienced developers will definitely inspect SFML code and get inspired by the idioms they see here. I think SFML should continue promoting good C++.

That said, seeing sf::NonCopyable - how simple, useful and concise it is - some may think it's a great idea. But sf::NonCopyable is in fact a code smell, syntactic sugar. The class can be inherited publicly which causes trouble with polymorphic destruction of base classes, and even the documentation says public inheritance does not matter here:
Quote
/// The type of inheritance (public or private) doesn't matter,
/// the copy constructor and assignment operator are declared private
/// in sf::NonCopyable so they will end up being inaccessible in both
/// cases.

To be safe it would require a virtual destructor which imposes an additional cost. Sure, private inheritance is safe but it's still ambiguous when somebody inherits directly from NonCopyable but provides a copy constructor or adds default move constructor/assignment anyways which separates statements of the move "=delete"s from NonCopyable.

All that mess for questionable readability/simplicity.