2

Let's say I want to create some classes to manage resources that shouldn't be copied nor moved, which would be the minimal class to extend and avoid mistakes?

The idea is that by extending the class, I end on the safe side of the 0/3/5 rules.

I have this in mind, which apparently works.

class NOCOPYNOMOVE {
    NOCOPYNOMOVE(NOCOPYNOMOVE &v) = delete;
    NOCOPYNOMOVE(NOCOPYNOMOVE &&v) = delete;
    NOCOPYNOMOVE& operator=(NOCOPYNOMOVE &r) = delete;
    NOCOPYNOMOVE& operator=(NOCOPYNOMOVE &&r) = delete;
};

class Foo: private NOCOPYNOMOVE {
public:
    Foo() {}
    ~Foo() {}
};
Josu Goñi
  • 1,178
  • 1
  • 10
  • 26
  • 2
    what's the question? – asmmo Aug 30 '21 at 10:52
  • I think you'r pretty close, not sure you need to delete operator=(&&). I never do it, but maybe it is a learning point for me. I also would make the default constructor protected. That way you can't accidentally make instances. – Pepijn Kramer Aug 30 '21 at 10:53
  • @PKramer I think it is indeed not needed as it won't be automatically generated, but this is more explicit. – Josu Goñi Aug 30 '21 at 10:55
  • 1
    When asking about `minimal` - you could omit the parameter names. So `(NOCOPYNOMOVE &)` instead of `(NOCOPYNOMOVE &v)`. – Brotcrunsher Aug 30 '21 at 10:56
  • @asmmo I have posted what appears to be a solution, but I'm not sure whether it is correct, since C++ can be very tricky (ideally, everything would be "delete" by default). – Josu Goñi Aug 30 '21 at 10:57
  • *... it is indeed not needed...* and *...the minimal class...* seem to be in conflict. – Eljay Aug 30 '21 at 12:40
  • It's [been done](https://www.boost.org/doc/libs/1_77_0/libs/core/doc/html/core/noncopyable.html). – Pete Becker Aug 30 '21 at 13:32

1 Answers1

2
  • Don't need to delete move constructor, see https://stackoverflow.com/a/38820178/2945027
  • Avoid ALL_CAPS name, as it is conventionally by every convention used for macros
  • There's no reason to omit const in copy constructor/assignment, so the usual form should be preferred
  • If classes would inherit from some NOCOPYNOMOVE in some namespace, it may trigger unintended ADL. boost::noncopyable solves it by putting the definition in noncopyable_ namespace, see the implementation
  • I'd prefer just not having some base, instead spelling out these two or three lines in the target class:
class Foo {
public:
    Foo() {}
    ~Foo() {}

    Foo(const Foo&) = delete;
    Foo& operator=(const Foo&) = delete;
};
Alex Guteniev
  • 12,039
  • 2
  • 34
  • 79
  • Yeah, I was using `ALL_CAPS` because I was thinking on writing something like a macro. Would be interesting to add the two lines as a macro too, but I don't know whether it is possible to get the class name inside the macro. Adding the last 2 lines by itself does not make the intention clear. – Josu Goñi Aug 30 '21 at 12:36