205

I have a class:

class SymbolIndexer {
protected:
  SymbolIndexer ( ) { }

public:
  static inline SymbolIndexer & GetUniqueInstance ( ) 
  { 
    static SymbolIndexer uniqueinstance_ ;
    return uniqueinstance_ ; 
  }
};

How should I modify it to disable code like:

SymbolIndexer symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );

and only allow code like:

SymbolIndexer & ref_symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );
Dharman
  • 30,962
  • 25
  • 85
  • 135
Humble Debugger
  • 4,439
  • 11
  • 39
  • 56

3 Answers3

348

You can make the copy constructor private and provide no implementation:

private:
    SymbolIndexer(const SymbolIndexer&);

Or in C++11, explicitly forbid it:

SymbolIndexer(const SymbolIndexer&) = delete;
Joachim W
  • 7,290
  • 5
  • 31
  • 59
R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
  • 66
    Regarding the `delete` keyword I'd like to add the following. My current habit habit when designing a new class is to `delete` both the copy constructor and assignment operator immediately. I've found that, depending on context, they're mostly unnecessary and deleting them prevents some cases of unexpected behavior. If a situation occurs where a copy ctor may be needed, determine if it can be done with move semantics. If this is undesirable, provide an implementation for both(!) the copy ctor and assignment operator. Whether this is a good approach I'll leave up to the reader. – pauluss86 Feb 01 '14 at 13:14
  • 1
    @pauluss86 I like your approach but I wouldn't fully commit to it as I think the time spent following this pattern is greater than time saved by the errors it prevents. I simply forbid copy whenever not sure. – Tomáš Zato Jan 14 '16 at 09:37
  • @pauluss86 This is basically what Rust does: Move-by-default (and const-by-default). Very helpful in my opinion. – Kapichu Dec 31 '16 at 01:38
47

If you don't mind multiple inheritance (it is not that bad, after all), you may write simple class with private copy constructor and assignment operator and additionally subclass it:

class NonAssignable {
private:
    NonAssignable(NonAssignable const&);
    NonAssignable& operator=(NonAssignable const&);
public:
    NonAssignable() {}
};

class SymbolIndexer: public Indexer, public NonAssignable {
};

For GCC this gives the following error message:

test.h: In copy constructor ‘SymbolIndexer::SymbolIndexer(const SymbolIndexer&)’:
test.h: error: ‘NonAssignable::NonAssignable(const NonAssignable&)’ is private

I'm not very sure for this to work in every compiler, though. There is a related question, but with no answer yet.

UPD:

In C++11 you may also write NonAssignable class as follows:

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

The delete keyword prevents members from being default-constructed, so they cannot be used further in a derived class's default-constructed members. Trying to assign gives the following error in GCC:

test.cpp: error: use of deleted function
          ‘SymbolIndexer& SymbolIndexer::operator=(const SymbolIndexer&)’
test.cpp: note: ‘SymbolIndexer& SymbolIndexer::operator=(const SymbolIndexer&)’
          is implicitly deleted because the default definition would
          be ill-formed:

UPD:

Boost already has a class just for the same purpose, I guess it's even implemented in similar way. The class is called boost::noncopyable and is meant to be used as in the following:

#include <boost/core/noncopyable.hpp>

class SymbolIndexer: public Indexer, private boost::noncopyable {
};

I'd recommend sticking to the Boost's solution if your project policy allows it. See also another boost::noncopyable-related question for more information.

Community
  • 1
  • 1
firegurafiku
  • 3,017
  • 1
  • 28
  • 37
4

Make SymbolIndexer( const SymbolIndexer& ) private. If you're assigning to a reference, you're not copying.

Aaron Klotz
  • 11,287
  • 1
  • 28
  • 22