1

The following program works without error.

#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
class userContext {
public:
    int id;
    int value1;
    int value2;
    userContext():id(-1),value1(-1),value2(-1){}
    userContext(userContext &context) {
        this->id = context.id;
        this->value1 = context.value1;
        this->value2 = context.value2;
    }
};
int main() {
    userContext a;
    a.id = 1;
    a.value1 = 2;
    a.value2 = 3;
    // map<int,userContext> Map;
    // Map[1] = a;
    cout << a.value1 << endl;
    cout << a.value2 << endl;
    return 0;
}

But If I introduce a map, it gives an error. Why is it so?

#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
class userContext {
public:
    int id;
    int value1;
    int value2;
    userContext():id(-1),value1(-1),value2(-1){}
    userContext(userContext &context) {
        this->id = context.id;
        this->value1 = context.value1;
        this->value2 = context.value2;
    }
};
int main() {
    userContext a;
    a.id = 1;
    a.value1 = 2;
    a.value2 = 3;
    map<int,userContext> Map;
    Map[1] = a;
    cout << Map[1].value1 << endl;
    cout << Map[1].value2 << endl;
    return 0;
}

part of compilation error output:

locks.cpp:20:7:   required from here
/usr/include/c++/7/bits/stl_pair.h:292:17: error: ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = userContext]’ declared to take const reference, but implicit declaration would take non-const
       constexpr pair(const pair&) = default;

However, changing copy constructor signature to userContext(const userContext &context) resolves the compilation error and programs executes fine. Please explain.

Thanks!

7
  • 3
    #include <bits/stdc++.h> Don't do this. Your program is uncompilable on the platform that I would test on. Commented Dec 21, 2018 at 10:32
  • 1
    In addition, your copy constructor has a flaw in that it fails to copy the id member. So now you have fake copies being generated. Commented Dec 21, 2018 at 10:36
  • 4
    Your question is sort of a duplicate of Why C++ copy constructor must use const object?, but the answer to your question would be to remove your copy constructor implementation and let the compiler generate the default one for you. Commented Dec 21, 2018 at 10:39
  • 1
    @Debashish Please explain. This might help: stackoverflow.com/a/43607151/580083. Commented Dec 21, 2018 at 10:51
  • 1
    @MatthieuBrucher Agree, but it would be good to explain why std::map requires its mapped type to require such a standard copy constructor (edit: Bathsheba just did it in his answer). Commented Dec 21, 2018 at 10:53

1 Answer 1

4

A copy constructor that does not pass the copied object by const reference does not satisfy the requirements of an AllocatorAwareContainer which is one of the concepts requried by a std::map.

In the absence of your passing in an alternative allocator on the std::map construction, compilation will fail.

Reference: https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks !. one QS. If I put a cout <<"hello"<<endl; statement at the start of the copy constructor, then why is it not getting printed? Am I missing something?
@Debashish Maybe the copy constructor is not being called. Compilers are allowed to elide the copy constructor.
now it's confusing. the map needs the const argument in user-defined copy constructor and it did not even call it.
The code needs to be syntactically correct. Optimizing the code is a different issue after the compiler deems your code as being correct.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.