Sunday, May 20, 2018

c++ - Why is it not possible to instantiate pair with "non const" copy constructor while it is possible to instantiate one without?



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



[class.copy]/8:




The implicitly-declared copy constructor for a class X will have the
form




X::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& or const volatile M&. Otherwise, the implicitly-declared
copy constructor will have the form



X::X(X&)




Therefore, if the copy constructor of std::pair were to be implicitly declared, it would have the form pair::pair(pair &).



[dcl.fct.def.default]/1:




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-const T”, where T 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

plot explanation - Why did Peaches&#39; mom hang on the tree? - Movies &amp; TV

In the middle of the movie Ice Age: Continental Drift Peaches' mom asked Peaches to go to sleep. Then, she hung on the tree. This parti...