Отключить конструктор копирования

У меня есть класс:

class SymbolIndexer {
protected:
  SymbolIndexer ( ) { }

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

Как мне изменить его, чтобы отключить код, например:

SymbolIndexer symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );

и разрешить только код:

SymbolIndexer & ref_symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );

Ответ 1

Вы можете сделать конструктор копирования закрытым и не выполнять реализацию:

private:
    SymbolIndexer(const SymbolIndexer& that);

Или в С++ 11 явно запретите это:

SymbolIndexer(const SymbolIndexer& that) = delete;

Ответ 2

Если вы не возражаете против множественного наследования (в конце концов, это не так уж плохо), вы можете написать простой класс с частным конструктором копирования и оператором присваивания и дополнительно подклассировать его:

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

class SymbolIndexer: public Indexer, public NonAssignable {
};

Для GCC это дает следующее сообщение об ошибке:

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

Я не очень уверен, что это работает в каждом компиляторе. Существует связанный вопрос, но пока нет ответа.

UPD:

В С++ 11 вы также можете написать класс NonAssignable следующим образом:

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

Ключевое слово delete не позволяет членам создавать по умолчанию, поэтому их нельзя использовать далее в созданных по умолчанию членах, построенных по умолчанию. Попытка назначить дает следующую ошибку в 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 уже имеет класс только для той же цели, я предполагаю, что он даже реализован аналогичным образом. Класс называется boost::noncopyable и предназначен для использования как в следующем:

#include <boost/core/noncopyable.hpp>

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

Я бы рекомендовал придерживаться решения Boost, если это позволяет его политика проекта. Дополнительную информацию см. Также в другом boost::noncopyable вопросе.

Ответ 3

Сделайте SymbolIndexer( const SymbolIndexer& ) приватным. Если вы назначаете ссылку, вы не копируете.