Suppose you have the following class:
struct A {
A () {}
A (A &) = delete;
};
int main() {
std::pair 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 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
?
Answer
The implicitly-declared copy constructor for a class
X
will have the
formX::X(const X&)
if each potentially constructed subobject of a class type
M
(or
array thereof) has a copy constructor whose first parameter is of type
const M&
orconst volatile M&
. Otherwise, the implicitly-declared
copy constructor will have the formX::X(X&)
Therefore, if the copy constructor of std::pair
were to be implicitly declared, it would have the form pair::pair(pair &)
.
A function that is explicitly defaulted shall
be a special member function,
have the same declared function type (except for possibly differing ref-qualifiers and except that in the case of a copy constructor or
copy assignment operator, the parameter type may be “reference to
non-constT
”, whereT
is the name of the member function's class) as
if it had been implicitly declared, and
not have default arguments.
Since the declaration pair(const pair&) = default;
doesn't have the same declared function type as the copy constructor that would have been implicitly declared, and neither exception applies, the program is ill-formed.
No comments:
Post a Comment