Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the easiest way to emulate =delete in C++03 for restricting copy/assignment operations?

C++11 scratches an itch that's long bothered me by allowing you to mark implicitly compiler defined methods as verboten with the "= delete" syntax. Wikipedia for more info.

class Foo
{
public:
     Foo();
    ~Foo();

    // No copy
    Foo(Foo const &) = delete;
    Foo& operator=(Foo const &) = delete;
};

Copy and assignment operators for classes that I do not expect to have copied or assigned are always a pain to mess with. It's a lot of boiler-plate code to make them private and then often there's member data that don't have a default constructor that require some hand-waving to make the compiler happy on a function you just want no one to ever call.

class Bar
{
public:
   explicit Bar(UniqueResourceID id): m_data(id) { }
   ~Bar();

protected:
   SomeHandle  m_data; // no default constructor

// all this crap to keep from being able to copy.  Do not use any of these!!
private:
   Bar() { } // ERROR: m_data has no default constructor
   static UniqueResourceID s_invalidID; // now I'm making the problem worse,
                                        // because I don't actually need this
                                        // for anything real, except to shut
                                        // up some errors.
   Bar(Bar const &o): m_data(s_invalidID) { }
   Bar& operator =(Bar const &o): { return *this; }
};

Unfortunately, some of the compilers I have to use are not C++11 compilers and don't offer =delete. What's the best way of dealing with these? (Please tell me there's a better way than the second code snippet.)

like image 418
Philippe Chaintreuil Avatar asked Mar 18 '23 07:03

Philippe Chaintreuil


1 Answers

You are writing all the extra crap because you are actually defining the body of the deleted operators -- I don't think you have to, and what I do is just making the declaration with no implementation anywhere, like this;

class Bar
{
public:
   explicit Bar(UniqueResourceID id): m_data(id) { }
   ~Bar();

protected:
   SomeHandle  m_data; // no default constructor

private:
   Bar(); 
   Bar(Bar const &o);
   Bar& operator =(Bar const &o);
};

This is no more verbose than writing the method with = delete appended to it.

Edit: Your definition of

....
private:
   Bar() {}

Is actually dangerous as it allows the operator to be called from other methods of within Bar without any errors ever getting generated (linker or compiler)

like image 137
Soren Avatar answered Apr 26 '23 17:04

Soren