Избегать копирования по значению при инициализации ссылки

У меня есть интерфейс функции:

struct iFace {
  virtual Type& getType() = 0;
}

и идея состоит в том, чтобы получить это как:

iFace& iface = getIface();
Type& type = iface.getType();

однако иногда я делаю ошибку и пишу:

Type type = iface.getType();

какие копии по значению, что я хочу избежать. Однако, когда я делаю такие ошибки, компилятор не выдает предупреждение, потому что его допустимый синтаксис. Я хотел бы вызвать ошибку времени компиляции для этого, Вопрос, каковы мои альтернативы?

я думал о том, чтобы объявить конструктор копирования, но нигде не определять его, вызывая ошибку времени компоновки, если он используется, но тогда я не смогу использовать конструктор копирования в ЛЮБОЙ ситуации, что менее чем желательно

2 ответа

Решение

Сделайте iFace некопируемым, поместив конструктор копирования и оператор присваивания в "private". Затем предоставьте явный метод копирования.

class Type {
public:
  virtual Copy(Type& dest) = 0;
private:
  Type (const Type &) {assert(false)}
  Type & operator=(const Type &)  {assert(false)}
}

Вы также можете использовать boost noncopyable, чтобы сделать то же самое (это реализовано, как описано выше).

Так что, если вы хотите, чтобы ваш код копировал, вы бы сделали

Type& type = iface.getType();
Type typeCpy;
type.Copy(typeCpy);

Кроме того, я бы добавил, что если вы делаете это из-за проблем с производительностью, уверены ли вы, что оптимизатор не избавится от временной копии за вас?

Возврат указателя здесь кажется разумным, но если вас беспокоит запутанная собственность, вы можете вернуть обертку вокруг ссылки.

struct Class {
    struct Ref {
        Ref(Class& c_) : c(c_) { }
        Class Clone() { return c; }
        // overload -> to provide access to c
      private:
        Class& c;
    };
};

Исходный класс можно копировать как обычно, но ссылку на него нужно делать явно. Я не в восторге от этой идеи (я бы подумал меньше о пользователе, который не понимал, как работает семантика копирования, чем о том, кто случайно держал один из них слишком долго), но теоретически это выполнимо.

Другие вопросы по тегам