假设您有以下课程:
struct A {
A () {}
A (A &) = delete;
};
int main() {
std::pair<A, int> p1;
return 0;
}
以下代码将无法编译(使用带有 g++
的 -std=c++11
),并出现以下错误:
/ usr / include / c /5/bits/stl_pair.h:在'struct std :: pair'的实例化中:test.cpp:13:23:从这里需要/ usr / include / c / 5 / bits / stl_pair .h:127:17:错误:'constexpr std :: pair <_T1,_T2> :: pair(const std :: pair <_T1,_T2>&)[与_T1 = A; _T2 = int]'声明采用const引用,但隐式声明将采用非const constexpr对(const pair&)= default;
根据错误消息,我认为这是因为由于 std::pair
参数上的 const
限定符,无法实现默认的复制构造函数 .
我能理解为什么在没有 = delete
的情况下不能编译,因为不可能实现带有 std::pair const&
参数的复制构造函数 .
但是对于 = delete
,我希望编译器不会实例化这样的构造函数,因为它不能(据我所知) . 实际上,这个拷贝构造函数被删除,如下面这段代码所示:
std::pair<A, int> p1;
decltype(p1) p2(p1);
失败了:
test.cpp:11:23:错误:使用已删除的函数'constexpr std :: pair <_T1,_T2> :: pair(const std :: pair <_T1,_T2>&)[与_T1 = A; _T2 = int]'decltype(p1)p2(p1);
基本上,我的问题是:为什么编译器无法实例化 std::pair
的已删除的复制构造函数?
2 回答
[class.copy]/8:
因此,如果要隐式声明
std::pair<A, int>
的复制构造函数,则其形式为pair::pair(pair &)
.[dcl.fct.def.default]/1:
由于声明
pair(const pair&) = default;
与已隐式声明的复制构造函数没有相同的声明函数类型,并且两个都不适用,因此程序格式错误 .如果你想
= delete
复制构造函数,正确的形式是:A(const A&) = delete;
. 看你怎么忘了const
?pair
可以与不可复制的类型一起使用,甚至是不可移动的类型 .您的实例化问题也可以通过以下方式证明:
要么...
基本上,它的副本ctor,并将其定义为
const pair&
,但是你的一个类型将它定义为采用非const&,因此默认生成失败,因为它可以't pass it'的const和非const& . 虽然你的版本是= delete
,但它并没有达到目标 .如果成员或基类不可复制,则有效删除默认复制文件 . 但为了弄明白这一点,它必须有一个能够调用的函数(即使该函数被删除) . 在这些情况下,它不能传递const&到非const&所以它甚至无法弄清楚你有一个删除的副本ctor . 可以想象,可以编写标准中的某些内容以适应这种边缘情况 .