Странная ошибка при попытке сделать swap shared_ptr ()

Я относительный новичок в C++, пытающийся преобразовать существующий проект из необработанных указателей с запутанным протоколом управления памятью в использование C++11 shared_ptr, В целом все идет очень гладко, и я думаю, что понимаю, как shared_ptr работает с точки зрения семантики перемещения, ссылок на значения и т. д. Хорошие вещи.

Однако я натолкнулся на странную ошибку, которую не понимаю и не могу исправить. Сначала немного истории. У меня есть иерархия классов коренится в абстрактном базовом классе с именем EidosValue и класс с именем EidosValue_Int_vector является (косвенно) конкретным подклассом этого:

class EidosValue
class EidosValue_Int : public EidosValue
class EidosValue_Int_vector : public EidosValue_Int

Мой код вообще трафик в EidosValue, но иногда, особенно при создании нового значения, мне нужно обрабатывать определенный подкласс.

Я сделал typedefs для shared_ptr s для этих классов, поэтому у меня есть:

typedef std::shared_ptr<EidosValue> EidosValue_SP;
typedef std::shared_ptr<EidosValue_Int_vector> EidosValue_Int_vector_SP;

среди других. Хорошо, теперь к сути проблемы. У меня есть функция, которая возвращает EidosValue_SP что это создает. В зависимости от логики внутри функции, она может создать один из нескольких конкретных подклассов EidosValue, Поэтому я делаю что-то вроде этого:

EidosValue_SP MyClass::MyMethod(...)
{
    EidosValue_SP result;

    if (...)
    {
        EidosValue_Int_vector_SP int_result_SP = make_shared<EidosValue_Int_vector>();
        ... do subclass-specific stuff with int_result_SP...
        result.swap(int_result_SP);
    }
    else (...)
    {
        ...similar logic for other subclasses...
    }

    ...other shared logic...
    return result;
}

Проблема с swap() вызов. Я получаю ошибку: " Non-const lvalue reference to type 'shared_ptr<EidosValue>' cannot bind to a value of unrelated type 'shared_ptr<EidosValue_Int_vector>' ". Это загадочно, так как EidosValue_Int_vector это не "не связанный тип", это открытый подкласс EidosValue, и код здесь это знает. Если я наберу result = make_shared<EidosValue_Int_vector>(); у компилятора нет никаких проблем с этим, поэтому он четко знает, что типы связаны и совместимы. Это просто не нравится в контексте swap() по какой-то причине. В других местах в моем проекте я мог просто сделать return int_result_SP; с объявленным типом возврата EidosValue_SP, и это сработало нормально - компилятор с радостью рассматривает EidosValue_Int_vector_SP как EidosValue_SP в этом контексте - но я не могу сделать это здесь из-за общей логики в нижней части функции,

Я несколько ограничен в своей реализации здесь, потому что этот код является узким местом и должен быстро выполняться (и да, я знаю это по факту инструментирования кода, и да, это действительно имеет значение). Поэтому важно использовать make_shared чтобы избежать двойного распределения, и я также настоятельно предпочел бы избегать увеличения / уменьшения счетчика при передаче указателя из int_result_SP в результате; Я не хочу, чтобы был момент времени, когда есть два shared_ptrs, указывающих на новый экземпляр. Так swap() кажется очевидным путем; но я заблокирован этой ошибкой компилятора. Почему это происходит и как я могу это исправить? Спасибо!

ДОПОЛНЕНИЕ:

О, размышляя об этом, держу пари, я знаю, почему происходит ошибка. swap() не возражает против EidosValue_Int_vector в EidosValue_SP, но у него есть проблема с EidosValue в EidosValue_Int_vector_SP; в этом направлении типы не совместимы. Я не думал об этом с тех пор result не имеет значения (т.е. имеет nullptr Наверное) в этом; но конечно swap() не знает этого Хорошо, так что если это проблема, то остается вопрос: как я могу осуществить передачу, сохраняя при этом код быстро - не делая refcount inc/dec и не отказываясь от использования make_shared? Теперь, когда я понимаю проблему (я думаю), кажется вероятным, что есть какой-то API или трюк, который я упустил из виду...

2 ответа

Решение

Это именно то, что std::move для. Использование:

    result = std::move (int_result_SP);

Ты не можешь swap потому что, хотя EidosValue_Int_vector это EidosValue обратное неверно.

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