Upcast unique_ptr с шаблоном - PullRequest
       5

Upcast unique_ptr с шаблоном

0 голосов
/ 09 марта 2019

Рассмотрим следующий простой код:

#include <memory>

template<typename T>
struct Foo
{
    virtual T & foo() = 0;
};

struct Bar : public Foo<int>
{
    int x;
    virtual int & foo() override
    {
        return x;
    }
};

void baz(std::unique_ptr<Foo<int>>)
{
}

int main()
{
    auto up = std::make_unique<Bar>();
    baz(up);
    return 0;
}

Он не скомпилирует сообщение об этой ошибке:

prog.cc:27:9: error: could not convert 'up' from 'unique_ptr<Bar,default_delete<Bar>>' to 'unique_ptr<Foo<int>,default_delete<Foo<int>>>'
   27 |     baz(up);
      |         ^~
      |         |
      |         unique_ptr<Bar,default_delete<Bar>>

Интересно, как я могу решить эту проблему.share_ptr, кажется, имеет надлежащие методы приведения, чтобы решить эту проблему , в то время как кажется, что для unique_ptr альтернативы нет.

1 Ответ

2 голосов
/ 09 марта 2019

Прежде всего, вы берете аргумент в baz значением , что подразумевает копирование a std::unique_ptr и ... это невозможно (или std::moveно я сомневаюсь, что это то, что вам нужно).

Во-вторых, std::unique_ptr не конвертируется, потому что это потребует копирования.

Какой обходной путь?

Вы можете сделать:

std::unique_ptr<Foo<int>> up = std::make_unique<Bar>();

вместо:

auto up = std::make_unique<Bar>();

и взять аргумент в baz по ссылке :

void baz(std::unique_ptr<Foo<int>>&) { ... }

Первым делом нужно сохранить unique_ptr в производной от unique_ptr базы.auto не может этого сделать, если вы не используете приведение.

Во-вторых, как уже упоминалось, не копируйте unique_ptr.

Более того, выкод демонстрирует неопределенное поведение , потому что вы удаляете объект производного класса с указателем базового класса.Для этого требуется базовый класс virtual.

...