33

There's a boost::noncopyable and I have my own noncopyable class in my library. Is there a std::noncopyable or equivalent knocking around in the latest C++ standard?

It's a small thing but deriving from such a class makes the intention much clearer.

Robinson
  • 9,666
  • 16
  • 71
  • 115

2 Answers2

26

No, because there is a standard way to make a class non-copyable:

class MyClass
{
   MyClass(const MyClass&) = delete;
   MyClass& operator=(const MyClass&) = delete;
}:

A class that is non-copyable can however be made movable by overloading a constructor from MyClass&&.

The declaration to make the class non-copyable (above) can be in the public or private section.

If you don't really want to type all that out every time, you can always define a macro something like:

#define NONCOPYABLE(Type) Type(const Type&)=delete; Type& operator=(const Type&)=delete

class MyClass
{
    NONCOPYABLE(MyClass);

    // etc.
};



  
CashCow
  • 30,981
  • 5
  • 61
  • 92
  • 19
    You need to delete a copy-assignemnt operator as well to make the class non-copyable – Piotr Skotnicki Aug 11 '15 at 11:49
  • 1
    @PiotrSkotnicki I added that to my answer before seeing your comment but well that makes it non-assignable. – CashCow Aug 11 '15 at 11:52
  • OK about those move semantics. They don't physically move the object somewhere else do they - the compiler is simply transferring the reference? So when you say assignment, you mean copy I assume (just for clarification). – Robinson Aug 11 '15 at 11:54
  • 1
    moving can be implemented like "swap" or it can leave 2 copies that look the same but the original item no longer has "ownership" so when it is deleted it doesn't delete the data. The state of the moved object must be stable but doesn't have any other guarantees. The state of the moved-to object should be the same as the moved one was. – CashCow Aug 11 '15 at 11:57
  • 1
    *"but well that makes it non-assignable"* so assignmant is not a copy operation? `boost::noncopyable` won't let you copy-assign one instance to another – Piotr Skotnicki Aug 11 '15 at 12:02
  • 1
    Indeed boost::noncopyable also makes the class non-assignable. Usually you want to disable that when you don't allow copying. – CashCow Aug 11 '15 at 12:09
  • 10
    So in conclusion then, funnily enough, the "standard C++ way" of doing it is fraught with trouble, mostly because developers aren't 100% sure how they should do it. I mean if I were to do this again I'd go google it. I think there's a definite need for it in the standard library. – Robinson Oct 19 '16 at 15:22
25

I'm sure you already figured it out by reading CashCow's post, but I thought I might as well provide a base class for noncopyable classes.

class Noncopyable {
public:
    Noncopyable() = default;
    ~Noncopyable() = default;

private:
    Noncopyable(const Noncopyable&) = delete;
    Noncopyable& operator=(const Noncopyable&) = delete;
};
user2015735
  • 419
  • 5
  • 6
  • 3
    This is what Scott Meyers recommends (page 39 Effective C++ 3rd ed.) – David Feb 14 '18 at 16:46
  • 9
    I think making the deleted methods as 'public' instead of 'private' would be better so that the compiler would first complain about the use of deleted function rather than access to private function. http://coliru.stacked-crooked.com/a/ee5ef146f1a9b24c – Chenna V Mar 08 '18 at 06:41
  • 1
    Shouldn't the destructor be virtual? – Roman2452809 Jun 05 '19 at 11:36
  • @user2452809 this would all depend on the usage of the class. If you're handing around a "Noncopyable" and then deleting it; sure. If you're passing around a "NoncopyableDerived" then no. – UKMonkey Sep 06 '19 at 11:19
  • 1
    @why is the destructor needed at all? Isn't it defaulted unless provided explicitly? – Baruch Jun 21 '20 at 09:11
  • 1
    There is no need to put the NonCopyable into private when it uses =delete it works wherever it is defined. Therefore it's simpler to make a macro if you don't want to write it out every time. – CashCow Nov 06 '20 at 12:15
  • 3
    The default constructor and destructor should be `protected`, since it would make no sense to instantiate an object of `Noncopyable` directly, only (notionally) as a base class of some derived, actually useful type. – underscore_d Apr 17 '21 at 11:11
  • 2
    That said, a macro is basically never the answer, and I don't see how it is desirable here. – underscore_d Apr 17 '21 at 11:12