Передача std::unique_ptr в качестве параметра функции

Я получил структуру и функцию, подобную следующей:

struct MYOVERLAPPED : public OVERLAPPED
{
    //...
};


void func1(std::unique_ptr<MYOVERLAPPED> pBuf)
{
    //...
};

Я получаю указатель на MYOVERLAPPED, который я хочу передать функции func1. Проблема, с которой я сталкиваюсь, заключается в том, что независимо от того, что я пытаюсь, я получаю следующие ошибки:

То, что я уже пробовал, это следующее: Try1:

std::unique_ptr<OVERLAPPED> pOver(//....)
HandleAcceptIndication(std::move(pOver));

Ошибка: ошибка 1 ошибка C2440: "инициализация": невозможно преобразовать из "_OVERLAPPED **" в "MYOVERLAPPED *"

Try2:

HandleAcceptIndication(new ACCEPT_OVERLAPPED);

Ошибка 1 ошибка C2664: "HandleAcceptIndication": невозможно преобразовать параметр 1 из "MYOVERLAPPED *" в "std::unique_ptr<_Ty>"

Кто-нибудь знает, как я могу передать этот приведенный указатель OVERLAPPED в MYOVERLAPPED в функцию и почему Try2 тоже не работает, так как я случайно использую std::unique_ptr<MYOVERLAPPED> pO(new MYOVERLAPPED) который работает...?

3 ответа

Решение

Пока вы не можете конвертировать из std::unique_ptr<base> в std::unique_ptr<derived> непосредственно, не так уж сложно написать функцию приведения, которая будет безопасна (то есть не утечет ресурс ни при каких обстоятельствах и будет успешной только в том случае, если приведение действительно:

template <typename Dst, typename Src>
std::unique_ptr<Dst> unique_dynamic_cast( std::unique_ptr<Src>& ptr ) {
    Src * p = ptr.release();                             // [1]
    std::unique_ptr<Dst> r( dynamic_cast<Dst*>(p) );     // [2]
    if ( !r ) {
        ptr.reset( p );                                  // [3]
    }
    return r;                                            // [4]
}

Основная идея заключается в том, что нам нужно извлечь указатель из std::unique_ptr и отложите его в [1]. Мы не можем попробовать dynamic_cast прямо, как будто это не удается, ptr освободил бы владение, и память просочилась бы. Затем мы пытаемся выполнить dynamic_cast [2] из локального указателя на запрошенный тип указателя и передать владение на r результат уникальный указатель. Если dynamic_cast не получается, тогда r будет нулевым, и нам нужно вернуть владение памятью оригиналу std::unique_ptr [3], для вызова кода, чтобы решить, что с ним делать. Затем мы возвращаем преобразованный std::unique_ptr звонящему в [4].

Это не работает, потому что вы пытаетесь использовать неверный путь в иерархии наследования. Вы пытаетесь конвертировать из Base* в Derived* неявно.

unique_ptr<A> а также unique_ptr<B> несвязанные типы. Вы не можете конвертировать между ними, если не существует неявного преобразования между A* а также B* (спасибо UncleBens), что в данном случае неверно. Кроме того, вы не должны понижать иерархию наследования с экземпляром, который не является подклассом, к которому вы приводите. В этом случае вы пытаетесь разыграть OVERLAPPED к MYOVERLAPPED который является неверным приведением, потому что OVERLAPPED это не MYOVERLAPPED, Вот почему вы не можете конвертировать между unique_ptr Типы в первую очередь.

Если вы просто пытаетесь передать unique_ptr в func1, вы можете сделать это так:

func1(shared_ptr<MYOVERLAPPED>(new MYOVERLAPPED));

Кроме того, передавая unique_ptr для функции указатель в оригинале устанавливается в NULL. Рассмотрите возможность использования ссылок или shared_ptrЕсли вы не создаете unique_ptr в качестве временного и передачи его функции, и вам нужно использовать тот же экземпляр позже.

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