用户提供的构造函数与显式默认的构造函数

User-provided constructor vs explicitly defaulted one

N4296::12.8/11 [class.copy] 告诉我们以下内容:

A defaulted copy/move constructor for a class X is defined as deleted (8.4.3) if X has:

[...]

(11.2) — a potentially constructed subobject type M (or array thereof) that cannot be copied/moved because overload resolution (13.3), as applied to M’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor

[...]

所以不清楚为什么这个程序

struct X
{
};

struct Y
{
    X&& x; 
    Y(Y const&)= default;
};

int main() { }

DEMO

工作正常,但以下内容:

struct X
{
};

struct Y
{
    X&& x; 
    Y(Y const&);
};

Y::Y(Y const&)= default; //error

int main() { }

DEMO

[dcl.fct.def.default]/p5,强调我的:

A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration. 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.

这是有道理的,因为对已删除函数的任何使用都会导致程序格式错误,但是对于用户提供的显式默认函数,可能无法在调用站点进行诊断:

// y.h
struct X
{
};

struct Y
{
    X&& x; 
    Y(Y const&);
};

// y.cpp
#include "y.h"
Y::Y(Y const&)= default; //defined as deleted

// main.cpp
#include "y.h"

int main() {
   Y y = Y();
}

编译main.cpp时,编译器不知道Y的复制构造函数存在;它不知道它是默认的,并且不可能诊断它实际上被删除了。唯一可以诊断出此类错误的地方是明确默认函数的地方。