I am writing a template function which accepts a custom class (that can be any class or primitive type) as a template argument, then reads some data (of that type) from an input stream, and then stores it an unordered map similar to this one:
std::unordered_map<CustomClass, std::vector<CustomClass>> map;
I have implemented a custom class to test the behavior. I have overloaded the std::hash so that this class can be stored in an unordered map as a key and overloaded all operators and constructors such that whenever they are called, I get a message in the console (example, when a copy constructor is called, I get a message "copy constructor [..data...]")
EDIT: As requested in the comments, here is the custom class definition and implementation (please note: the class here is only a placeholder so we can discuss the general idea behind this question. I am well aware that it is dumb and should not be implemented like this. The code for operators >> and << is not here, to avoid clutter)
class CustomClass {
public:
CustomClass(int a=0) {
std::cout << "default constructor" << std::endl;
m_data = a;
}
CustomClass(const CustomClass& other) {
std::cout << "copy constructor " ;//<< std::endl;
m_data = other.m_data;
std::cout << "[" << m_data << "]" << std::endl;
}
CustomClass(CustomClass&& other) {
std::cout << "move cosntructor" << std::endl;
m_data = other.m_data;
}
CustomClass& operator=(const CustomClass& other) {
std::cout << "copy assignment operator" << std::endl;
if(this != &other){
m_data = other.m_data;
}
return *this;
}
CustomClass& operator=(CustomClass&& other) {
std::cout << "move assignment operator" << std::endl;
if(this != &other){
m_data = other.m_data;
}
return *this;
}
~CustomClass() {
std::cout << "destructor" << std::endl;
}
int m_data;
};
Now my question is this: Is it possible to read data from the input stream and construct it inplace where it is needed without a copy constructor call?
Example of some code:
CustomClass x1; // default constructor call
CustomClass x2; // default constructor call
std::cout << "----" << std::endl;
std::cin >> x1 >> x2; // my input
std::cout << "----" << std::endl;
map[x1].emplace_back(x2); // 2 copy constructor calls
std::cout << "----" << std::endl;
std::cout << map[x1][0] << std::endl; // operator== call
std::cout << "----" << std::endl;
And here is an example output from that code:
default constructor
default constructor
----
[1]
[2]
----
copy constructor [1]
copy constructor [2]
----
operator ==
[2]
----
destructor
destructor
destructor
destructor
I would like to have it so that every object of this class is constructed only once.
Is it possible to avoid these copy constructors? If not both, then at least the one that is called during the emplace_back() call? Is it possible to construct the object in the vector exactly where it needs to be in memory but that this sort of call works for every type?
If I need to further elaborate on my question please tell me in the comments, I will be happy to do so