c++classpointersstdmap

Call to implicitly deleted copy constructor when using smart pointer with std::map()


I am trying to implace a class object into a std::map, and error occurs. Here is the code:

classes.hpp

#ifndef CLASSMETHODNOTCALLED_CLASSES_HPP
#define CLASSMETHODNOTCALLED_CLASSES_HPP

#include "iostream"
#include "memory"

// tow classes with one pointing to the other

class Ca
{
    int m_va = 5;
public:
    Ca();
    int getVa();
};


class Cb
{
    std::unique_ptr<Ca> m_x; // a smart ptr pointing to class Ca
    int m_vb;
public:
    explicit Cb(int n);
    ~Cb();
    int getCa();
};
#endif //CLASSMETHODNOTCALLED_CLASSES_HPP

classes.cpp

#include "../include/classes.hpp"
#include "memory"

// Ca
Ca::Ca()
{

}

int Ca::getVa()
{
    return m_va;
};

// Cb
Cb::Cb(int n)
{
    m_x = std::make_unique<Ca>();
    m_vb = n;
}

Cb::~Cb()
{
}

int Cb::getCa()
{
    return m_x->getVa() + m_vb; // returns 5 + 1 = 6 if works properly
}

main.cpp

#include <iostream>
#include "include/classes.hpp"
#include "map"

int main()
{
    Cb cb(1);  // instanciate Cb

    std::map<int, Cb> m;
    m.emplace(1, cb); // the line where it complains: Call to implicitly deleted copy constructor
    int i = m.at(1).getCa(); // should return 6 if working properly

//    int i = cb.getCa(); // code without using std::map() works

    std::cout << "va = " << i << std::endl;
}

I think it is caused by the smart pointer whose constructor is explicitly deleted. My question is, how to insert cb into a std::map() in this case? Thank you!

UPDATE:

Now I am trying to get a Cb object from the map, and here is what I did

int main()
{
    Cb cb(1);  // instanciate Cb

    std::map<int, Cb> m;
    m.emplace(1, std::move(cb));

    Cb ccb = m.at(1); // error occurs here complaining Call to implicitly deleted copy constructor
    int i = m.at(1).getCa();

//    int i = cb.getCa();

    std::cout << "va = " << i << std::endl;
}

Any idea?


Solution

  • emplace takes parameters and forwards them to the contructor of the element of the map. If you pass it a Cb it will copy it, if you pass it a rvalue ref it will move it and if you pass it a 1 it will use that to construct the Cb.

    Hence, you can

    But you cannot ask emplace to copy a Cb because Cb has no copy constructor.