Suppose you have the following class:
struct A {
A () {}
A (A &) = delete;
};
int main() {
std::pair<A, int> p1;
return 0;
}
The following code will fail to compile (using -std=c++11
with g++
) with the following error:
/usr/include/c++/5/bits/stl_pair.h: In instantiation of ‘struct std::pair’:
test.cpp:13:23: required from here
/usr/include/c++/5/bits/stl_pair.h:127:17: error: ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = A; _T2 = int]’ declared to take const reference, but implicit declaration would take non-const
constexpr pair(const pair&) = default;
According to the error message, I would assume that this is because it is not possible to instanciate the default copy constructor because of the const
qualifier on the std::pair
argument.
I could understand why this would not compile without the = delete
, because it is not possible to instanciate the copy constructor which takes a std::pair const&
parameter.
But with the = delete
, I would expect the compiler to not instantiate such constructor because it cannot (as far as I understand). Actually, this copy constructor is deleted as shown by this piece of code:
std::pair<A, int> p1;
decltype(p1) p2(p1);
Which fails:
test.cpp:11:23: error: use of deleted function ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = A; _T2 = int]’
decltype(p1) p2(p1);
Basically, my question is: Why does the compiler fails to instantiate a deleted copy constructor of std::pair
?
If you want to = delete
the copy constructor, the proper form is: A(const A&) = delete;
. See how you forgot that const
? pair
can be used with a non-copyable type, even a non-moveable type.
Your instantiation problem can also be demonstrated with:
struct A {
A(A&) = delete;
};
struct B : A {
B(const B&) = default;
};
or...
struct B {
B(const B&) = default;
A a;
};
Basically, pair
= default
its copy ctor, and defines it as taking a const pair&
, but one one of your types defines it to take a non-const &, so the default generation fails since it can't pass it's const& to your non-const&. Even though yours is = delete
ed, it doesn't matter, it doesn't get that far.
A defaulted copy ctor will effectively be deleted if a member or base class is non-copyable. But in order to figure that out, it has to have a function it is able to call (even if that function is deleted). In these cases, it can't pass a const& to a non-const& so it can't even figure out that you have a deleted copy ctor. Conceivably, something in the standard could be written to accommodate this edge case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With