ссылка unique_ptr на удаленную функцию при реализации интерфейса - PullRequest
0 голосов
/ 29 августа 2018

У меня есть следующий код, который создается с помощью цепочки инструментов MSVC2013, C ++ 11 (старые вещи, функция рабочих ограничений):

template<class T>
class AbstractWrappedQueue {
public:
    virtual bool empty() = 0;
    virtual size_t size() = 0;
    virtual void push(T& value) = 0;
    virtual void push(T&& value) = 0;
    virtual T pop() = 0;
};

template<class T>
class WrappedQueue // : public AbstractWrappedQueue<T>
{
private:
    std::queue<T> q;
public:
    WrappedQueue() {}
    ~WrappedQueue() {}
    bool empty() { return q.empty(); }
    size_t size() { return q.size(); }
    void push(T& p) { q.push(p); }
    void push(T&& p) { q.push(std::move(p)); }
    T pop() {
        T r = std::move(q.front());
        q.pop();
        return r;
    }
};

WrappedQueue<std::unique_ptr<int>> ptr;

Пока WrappedQueue стоит один, класс и его функциональность без проблем воспроизводятся с unique_ptr s. Однако, если он реализует интерфейс AbstractWrappedQueue (т. Е. Раскомментирует часть : AbstractWrappedQueue<T> определения класса, тогда я получаю следующую ошибку:

error C2280: 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function.

Я бы не ожидал, что приложение моего интерфейса вызовет ситуацию, когда может произойти попытка скопировать unique_ptr. Почему это происходит? Что можно сделать, чтобы предотвратить это (кроме простого отказа от интерфейса)?

1 Ответ

0 голосов
/ 29 августа 2018

Проблема в этой функции:

void push(T& p) { q.push(p); }

Это копирует p, и если p является std::unique_ptr<int>, это не сработает - это не копируется.

Если у вас просто есть WrappedQueue<T>, функции-члены, не являющиеся virtual, никогда не создаются, пока не будут фактически использованы. Так что это не ошибка, пока кто-то на самом деле не попытается push lvalue. Вот почему std::vector<T>::push_back(T const&) может существовать и в любом случае позволить вам иметь std::vector<std::unique_ptr<int>>. Это нормально - это только ошибка, когда вы пытаетесь сделать что-то явно неправильное.

Однако, если у вас есть AbstractWrappedQueue<T> - с виртуальными функциями-членами, и там правило более размытое: [temp.inst] / 10 :

Не определено, будет ли реализация неявно создавать экземпляр функции-члена шаблона класса, если в противном случае функция-член не была бы создана.

Ваша реализация в любом случае создает его экземпляр - и эта функция некорректна для T=std::unique_ptr<int>. Отсюда и проблема.

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

<ч />

Примечание: вы, вероятно, хотите push(T const&), а не push(T&).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...