Home > Back-end >  Cannot convert unique_ptr<derived> to unique_ptr<base>
Cannot convert unique_ptr<derived> to unique_ptr<base>

Time:08-06

There are 3 classes:

decoder_mqtt - Common decoder

subdecoder_mqtt_base - Base subdecoder for each concrete version (not an abstract class, but have virtual method).

subdecoder_mqtt_v5 : subdecoder_mqtt_base - Derived from subdecoder_mqtt_base subdecoder class.

decoder_mqtt creates a subdecoder:

// file: mqtt.cc
#include "mqtt_v5.h"
...
using subdecoder_ptr = std::unique_ptr<subdecoder_mqtt_base>;
...
decoder_base::result_t decoder_mqtt::decode_data(const char* data, size_t length)
{
    return subdecoder_put_data<subdecoder_mqtt_v5>(
                    data, length, SUBDECODERS_STATE::V5_REJECTED, _sd_mqtt_v5 );
}
...

template <class SUBDECODER_T>
decoder_base::result_t decoder_mqtt::subdecoder_put_data(
                                            const char* data, size_t length,
                                            SUBDECODERS_STATE sd_state_if_rejected, subdecoder_ptr& subdecoder)
{
    if (!(to_underlying(sd_state_if_rejected) & _subdecoders_state))
    {
        if (!subdecoder)
            subdecoder = std::make_unique<SUBDECODER_T>(this); // Error here!
        result_t res = subdecoder->reassemble_and_decode_data(data, length);
        if (!res)
        {
            _subdecoders_state |= to_underlying(sd_state_if_rejected);
            subdecoder = nullptr;
        }
        return res;
    }

    return result_t(false, 0);
}

Definition of a subdecoder_mqtt_v5:

class subdecoder_mqtt_v5 : subdecoder_mqtt_base
{
public:
    subdecoder_mqtt_v5(decoder_mqtt* d_mqtt);
    virtual ~subdecoder_mqtt_v5();

    virtual result_t reassemble_and_decode_data(const char* data, size_t length) override final;
    ....
};

GCC prints an error:

error: no match for ‘operator=’ (operand types are ‘decoder_mqtt::subdecoder_ptr’ {aka ‘std::unique_ptr<subdecoder_mqtt_base>’} and ‘std::_MakeUniq<subdecoder_mqtt_v5>::__single_object’ {aka ‘std::unique_ptr<subdecoder_mqtt_v5, std::default_delete<subdecoder_mqtt_v5> >’})

/usr/include/c  /9/bits/unique_ptr.h:305:7: note: candidate: ‘std::unique_ptr<_Tp, _Dp>& std::unique_ptr<_Tp, _Dp>::operator=(std::unique_ptr<_Tp, _Dp>&&) [with _Tp = subdecoder_mqtt_base; _Dp = std::default_delete<subdecoder_mqtt_base>]’
  305 |       operator=(unique_ptr&& __u) noexcept
      |       ^~~~~~~~
/usr/include/c  /9/bits/unique_ptr.h:305:30: note:   no known conversion for argument 1 from ‘std::_MakeUniq<subdecoder_mqtt_v5>::__single_object’ {aka ‘std::unique_ptr<subdecoder_mqtt_v5, std::default_delete<subdecoder_mqtt_v5> >’} to ‘std::unique_ptr<subdecoder_mqtt_base>&&’
  305 |       operator=(unique_ptr&& __u) noexcept


What am I doing wrong? Elsewhere, similar code compiles.

CodePudding user response:

What am I doing wrong?

subdecoder_mqtt_v5 privately derives from subdecoder_mqtt_base, so there is only an implicit conversion of pointers in the members and friends of subdecoder_mqtt_v5. The unique_ptr constructor is not one of those places.

You probably meant to publicly inherit:

class subdecoder_mqtt_v5 : public subdecoder_mqtt_base
  • Related