0

I have read many topics about this on SO and no solution worked for me so far, so I must be doing something wrong.

This works:

std::vector<CalendarDay*> calendarWeek;
calendarWeek.push_back(new CalendarDay(hWndParam, ctrlRc, timeParam, week * MY_CLDR_DAYS + day));

This does not work (and it should, according to this):

std::vector<std::unique_ptr<CalendarDay>> calendarWeek;
calendarWeek.push_back(std::unique_ptr<CalendarDay>(new CalendarDay(hWndParam, ctrlRc, timeParam, week * MY_CLDR_DAYS + day)));

This does not work either (and it should, according to this):

std::vector<std::unique_ptr<CalendarDay>> calendarWeek;
std::unique_ptr<CalendarDay> item(new CalendarDay(hWndParam, ctrlRc, timeParam, week * MY_CLDR_DAYS + day));
calendarWeek.push_back(std::move(item));

Neither does this:

std::vector<std::unique_ptr<CalendarDay>> calendarWeek;
std::unique_ptr<CalendarDay> item(new CalendarDay(hWndParam, ctrlRc, timeParam, week * MY_CLDR_DAYS + day));
calendarWeek.emplace_back(std::move(item));

Error is always the same:

Error   C2280   'std::unique_ptr<CalendarDay,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function

What am I doing wrong?

Full code sample:

//  DECLARED IN HEADER
std::vector<std::vector<std::unique_ptr<CalendarDay>>> calendar; // holds pointer to each day control in calendar


//  MEMBER FUNCTION
void Calendar::GenerateDays
(
      std::shared_ptr<Time> &timeParam // handles time information of displayed data
    , HWND hWndParam // handle to main window
)
{
    //  GENERATE DAY CONTROLS

    for (int week = 0; week < MY_CLDR_WEEKS; week++)
    {
        std::vector<std::unique_ptr<CalendarDay>> calendarWeek; // stores controls for one week
        for (int day = 0; day < MY_CLDR_DAYS; day++)
        {
            //  CREATE NEW CONTROL

            RECT ctrlRc // position of new control in main window
            {
                  daysOfstLeft + day * (dayWidth + dayOfst) // left border
                , daysOfstTop + week * (dayHeight + dayOfst) // top border
                , dayWidth // width
                , dayHeight // height
            };

            //  STORE DAY CONTROL IN VECTOR

            calendarWeek.reserve(sizeof(std::unique_ptr<CalendarDay>));
            calendarWeek.push_back(std::unique_ptr<CalendarDay>(new CalendarDay
            (
                  hWndParam
                , ctrlRc
                , timeParam
                , week * MY_CLDR_DAYS + day
            )));
        }
        calendar.reserve(sizeof(calendarWeek));
        calendar.push_back(calendarWeek);
    }
}
Ardent Coder
  • 3,309
  • 9
  • 18
  • 39
Irma
  • 17
  • 5
  • Both of the last versions work for me. Can you please provide a full [mcve]? – UnholySheep May 08 '20 at 19:34
  • They should work, and they do work on my machine. The problem is elsewhere in your code. – Azam Bham May 08 '20 at 19:35
  • @UnholySheep done. – Irma May 08 '20 at 19:38
  • That still isn't a complete example (as it's missing the definition of `CalendarDay`), but I'm pretty sure that the actual error stems from `calendar.push_back(calendarWeek);` and not `calendarWeek.push_back` – UnholySheep May 08 '20 at 19:39
  • 1
    using std::make_unique to construct the unique_ptr object is better than using raw ptr object and then passing it to a unique_ptr – ggulgulia May 08 '20 at 19:56

2 Answers2

4

Based on your code, it looks like the issue is with the last line of the function calendar.push_back(calendarWeek). It should be calendar.emplace_back(std::move(calendarWeek)), otherwise, you are attempting to copy the vector of std::unique_ptrs, and since std::unique_ptrs do not have a copy constructor, you are getting compile errors.

Azam Bham
  • 1,129
  • 3
  • 6
0

The error basically is indicating that the copy constructor of the object wrapped in a unique pointer is being called.

unique pointer has the semantics of unique ownership, meaning there is only a single ownership of an object, in your case CalendarDay object.

The following should work

std::vector<std::unique_ptr<CalendarDay>> calendarVec;

calendarVec.emplace_back(std::make_unique<CalendarDay>(hWndParam, ctrlRc, timeParam, week * MY_CLDR_DAYS + day);

If you really need to use an an existing unique pointer object you are allowed to transfer the object stored in the unique pointer using std::unique_ptr::release() method which releases the raw pointer. So you can do like this:

std::unique_ptr<CalendarDay> day{std::make_unique<CalendarDay>>(hWndParam, ctrlRc, timeParam, week * MY_CLDR_DAYS + day);
std::vector<std::unique_ptr<CalendarDay>> calendarVec;
calendarVec.emplace_back(day.release());

After transferring the object's ownership the object is no longer safe to use.

ggulgulia
  • 1,672
  • 18
  • 23