Search code examples
c++objectshared-ptr

Creating shared pointer of object taking shared pointer as parameter


Trying to create a std::shared_ptr of an object which takes a std::shared_ptr as a parameter resulted in a "no matching constructor for initialization of 'object'" compile error.

My code looks as following:

// Sidebar Widgets
  _widgets.sideBarWidgetLeft = std::make_shared<SideBarWidget>();
  _widgets.sideBarWidgetLeft->hide();
  _widgets.sideBarWidgetRight = std::make_shared<SideBarWidget>();
  _widgets.sideBarWidgetRight->hide();

  // Pointer Test
  CalibrationManagementWidget* test = new CalibrationManagementWidget( _widgets.sideBarWidgetLeft, 0 );

  // Sidebar Left
  _widgets.calibrationManagementWidget = std::make_shared<CalibrationManagementWidget>( _widgets.sideBarWidgetLeft, 0 );
  _widgets.calibrationManagementWidget->hide();
  _widgets.cameraWidget = std::make_shared<CameraWidget>( 0, VISUALISATION_TYPE_NORMAL );
  _widgets.cameraWidget->hide();

While "Pointer Test" compiles just fine, the lines under "Sidebar Left" create named error. Is there something I'm doing wrong instantiating or isn't this possible in general?

Here is (one of) the error message(s):

/usr/include/c++/5.4.0/ext/new_allocator.h:120: Error: no matching constructor for initialization of 'CalibrationManagementWidget'
        { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
                             ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~

EDIT:

As requested I'll post some snippets which contain also the constructor of the CalibrationWidget.

calibrationwidget.h

...
Q_INVOKABLE CalibrationManagementWidget(QWidget* parent = 0 , VisualisationType visuType = VISUALISATION_TYPE_TRANSLATOR);
CalibrationManagementWidget( std::shared_ptr<SideBarWidget> sideBarWidget, QWidget* parent = 0 );
virtual ~CalibrationManagementWidget();
...

calibrationwidget.cpp

...
CalibrationManagementWidget::CalibrationManagementWidget(QWidget* parent, enum VisualisationType visuType) : CommonWindowWidget( WIDGET_TYPE_3D, "", "Calibration Management", 0, Ui::UI_WINDOW_FLAG_CLOSABLE, 0, parent, visuType) {
  _currentMessage = 0;
  _selectedCalibrationType = CALIBRATION_TYPE_UNKNOWN;
  _messageEventLoop = new QEventLoop(this);
  _updateTimer = new QTimer();
  setupUi();
}


CalibrationManagementWidget::CalibrationManagementWidget(std::shared_ptr<SideBarWidget> sideBarWidget, QWidget* parent) : CommonWindowWidget( WIDGET_TYPE_3D, "", "Calibration Management", 0, Ui::UI_WINDOW_FLAG_CLOSABLE, sideBarWidget, parent) {
  _currentMessage = 0;
  _selectedCalibrationType = CALIBRATION_TYPE_UNKNOWN;
  _messageEventLoop = new QEventLoop(this);
  _updateTimer = new QTimer();
  setupUi();
}

CalibrationManagementWidget::~CalibrationManagementWidget() {
  delete _messageEventLoop;
  _messageEventLoop = 0;
  delete _updateTimer;
  _updateTimer = 0;
}
...

Here are also snippets from the CommonWindowWidget.

commonwindowwidget.h

...
CommonWindowWidget(WidgetType widgetType, const QString& headerTitle = "Foldable Widget", const string& pageName = "Foldable Widget", unsigned int view = 0, unsigned int uiWindowFlags = 0, std::shared_ptr<SideBarWidget> sideBarWidget = 0, QWidget* parent = 0, VisualisationType visuType = VISUALISATION_TYPE_NORMAL);
    virtual ~CommonWindowWidget();
...

commonwindowwidget.cpp

...
CommonWindowWidget::CommonWindowWidget(WidgetType widgetType, const QString& headerTitle, const string& pageName, unsigned int view, unsigned int uiWindowFlags, std::shared_ptr<SideBarWidget> sideBarWidget, QWidget* parent, VisualisationType visuType) : CommonStackedWidget(widgetType, pageName, view, parent, visuType) {
  _windowFlags = uiWindowFlags;
  _sideBarWidget = std::move(sideBarWidget);

  setupUi();

  _ui.headerWidget->headerLabel()->setText( headerTitle );

  connect( _ui.headerWidget, SIGNAL(headerDoubleClicked()), this, SLOT(changeFoldState()));
  connect( _ui.headerWidget, SIGNAL(changeFoldStateClicked()), this, SLOT(changeFoldState()));
  connect( _ui.headerWidget, SIGNAL(closeClicked()), this, SLOT(navigateToHome()));
}

CommonWindowWidget::~CommonWindowWidget() {

}
...

Solution

  • When forwarded, 0 causes the parameter to be deduced as int, which is not convertible to a pointer anymore.

    Only the literal 0 can represent a pointer, but after having been passed to make_shared, the literal becomes the int value 0, which causes the error, as the constructor expects a pointer.

    Use nullptr instead:

    _widgets.calibrationManagementWidget =
       std::make_shared<CalibrationManagementWidget>(
         _widgets.sideBarWidgetLeft, nullptr
       );
    

    This is the main reason why nullptr was introduced.

    Explanation: https://channel9.msdn.com/Shows/Going+Deep/Stephan-T-Lavavej-Everything-you-ever-wanted-to-know-about-nullptr, about minute 28:00.