Comparing two map::iterators: why does it need the copy constructor of std::pair?

China☆狼群 提交于 2019-12-02 22:43:26

The copy constructor of std::pair isn't needed in this case, but because it is default defined inline in the declaration of std::pair, it is automatically instantiated along with the instantiation of std::pair itself.

It would be possible for the standard library to provide a non-inline default definition of the copy constructor:

template<class _T1, class _T2>
  struct pair
  {
// ...
    constexpr pair(const pair&);
// ...
  };
// ...
template<class _T1, class _T2>
constexpr pair<_T1, _T2>::pair(const pair&) = default;

However this would not accord with the strict letter of the standard (clause 20.3.2), where the copy constructor is default defined inline:

  constexpr pair(const pair&) = default;

I think I found it after trying to reduce the error. First, the comparison doesn't seem required to make the program ill-formed. Then, the error message contained the dtor, so I tried not to instantiate the dtor. Result:

#include <map>

struct A {
    A(A& ); // <-- const missing
};

int main() {
    std::map<int, A>* m = new std::map<int, A>();
    // note: dtor not (necessarily?) instantiated
}

But the output message still contains, now for the line where the ctor of m is called:

error: the parameter for this explicitly-defaulted copy constructor is const, but a member or base requires it to be non-const

 constexpr pair(const pair&) = default;

Which hints to [dcl.fct.def.default]/4

A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed.

[emphasis mine]

If, as I assume, [class.copy]/11 says that this ctor should be defined as deleted, then it is defined as deleted immediately - not only when it's odr-used. Therefore, an instantiation shouldn't be required to make the program ill-formed.

std::map uses std::pair to store key-value pairs, where the key (the first element) is const.

The compiler error relates to the required copy constructor for std::pair, even if it isn't being used (which I don't think it is).

std::pair<int, A> has to be generated. This is first required with the call to map::begin. Since no explicit copy constructor is given for this type, the implicit one used.

The implicit constructor will have signature T::T(const T&) only if all non-static members of T, (type S), have copy constructors S::S(const S&) (the same requirement has to hold for T's base types copy constructors). Otherwise a copy constructor with signature T::T(T&) is used instead.

A's copy constructor fails this requirement, so std::pair::pair has the wrong signature for the STL, which requires T::T(const T&).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!