Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Non copyable except sometimes

I find that making a class non-copyable helps me a lot with my code quality. Initially I did this with boost::noncopyable, but I found the VC++ compiler errors to be not as helpful as with private members (double clicking lead to the wrong place in the code).

T(T const&);
T& operator=(T const&);

Indeed, it has alerted me to quite a few cases were classes were not passed as reference where they should have. So much so, that I would very much like to get a warning even on classes that I just need to copy construct once.

Is there a good way to do this? I was thinking for example of leaving above two methods private and adding a public T(T const&,bool dummy) constructor to call when I really want to copy construct. Or maybe alternatively make above two methods public and somehow activate a compiler warning when copy constructing, suppressing the warning where I do want to.

Or maybe there is an all together better way?

like image 533
Cookie Avatar asked Jul 07 '11 18:07

Cookie


2 Answers

Not sure if it's exactly what you want, but if you mark the copy constructor explicit then the class can't be passed by value or copy-initialized, but you can copy-construct using direct initialization.

You'd presumably want to keep the assignment operator private, maybe a NonAssignable base would be useful for that.

like image 58
Steve Jessop Avatar answered Nov 09 '22 19:11

Steve Jessop


I think you named a perfect way there yourself.

I just remembered a neat(?) little trick I once played in another code base I worked on:

struct T
{
    friend class SomeClientThatCanConstructT;
    T(T const&);

  private:
     T(T const&);           
};

As discussed in the comments the following won't fly

You might opt for an explicit name (like CopyConstruct) and rely on RVO to be equally efficient:

struct T
{
     inline T CopyConstruct() const     { return *this; }
     inline T& AssignTo(T& dst) const   { return dst = *this; }
     inline T& AssignFrom(const T& src) { return *this = src; }

  private:
     T(T const&);
     T& operator=(T const&);
};

like image 2
sehe Avatar answered Nov 09 '22 18:11

sehe