[英]While doing copy-elision, the compiler doesn't consider the copy constructor in overload resolution, when the move constructor is deleted. Why?
[英]Why doesn't the standard consider a template constructor as a copy constructor?
这是复制构造函数的定义, [class.copy.ctor / 1] :
如果X类的第一个参数是X&,const X&,volatile X&或const volatile X&,并且没有其他参数或者所有其他参数都有默认参数([dcl。],则X类的非模板构造函数是一个复制构造函数。 fct.default])。
为什么标准将模板排除为复制构造函数?
在这个简单的例子中,两个构造函数都是复制构造函数:
struct Foo {
Foo(const Foo &); // copy constructor
Foo(Foo &); // copy constructor
};
看到这个类似的例子:
struct Foo {
Foo() = default;
template <typename T>
Foo(T &) {
printf("here\n");
}
};
int main() {
Foo a;
Foo b = a;
}
在此示例中,将打印here
。 所以我的模板构造函数似乎是一个复制构造函数,至少它表现得像一个(它在通常调用复制构造函数的上下文中调用)。
为什么文本中存在“非模板”要求?
让模板放在一边一秒钟。 如果类未声明复制构造函数,则会生成隐式默认值。 它可能被定义为已删除,但它仍然是默认的。
成员模板不是成员函数。 成员仅在需要时才从中实例化。
那么编译器如何才能从类定义中知道是否需要使用T = Foo
? 它不能。 但正是在这个问题上,它需要根据如何处理隐式默认复制构造函数(AND移动构造函数)的潜在需求做出决定。 那变得凌乱。
最简单的方法是排除模板。 无论如何,我们总是会有一些复制构造函数,它默认会执行正确的TM ,并且会被重载解析所支持,因为它不是从模板中实例化的。
为什么文本中存在“非模板”要求?
鉴于它是不同的,复制构造函数可以是模板。 如果存在复制构造函数模板,非复制构造函数怎么可能不明确? 考虑一下:
struct Foo {
// ctor template: clearly useful and necessary
template <typename T>
Foo(const T&) {}
// copy ctor: same signature! can't work
template <typename T>
Foo(const T &) {}
};
此外,构造Foo
从一个对象,该对象是不是一个Foo
可以通过转化或普通的结构来实现的,但是允许从一个非复制结构Foo
对象改变复制的概念来复制包括转换 。 但这已经可以用现有方案(转换或非复制构造)实现。
在此示例中,将打印此处。 所以我的模板构造函数似乎是一个复制构造函数
您显示的示例不会调用复制构造,而是调用普通的隐式构造。 如果您将构造函数模板更改为
template <typename T>
Foo(const T &) {
// ^^^^^
printf("here\n");
}
那么Foo b = a;
导致编译器生成的复制构造函数被调用。 请注意,编译器生成的copy ctor具有以下签名:
Foo(const Foo&);
这需要增加一个const
-qualifier到a
在Foo b = a;
。 您的代码段中的原始构造函数模板Foo(T&)
是更好的匹配,因为没有添加const
-qualifier。
复制构造函数的形式为X(X&)或(X const&),如果您没有自己声明,它将由编译器为您提供。 如果您使用模板类,非模板可能会因此而出现问题。
假设有一个模板类,它有一个模板复制构造函数。 问题是,当您使用具有相同模板类型的此类的另一个实例来实例化该类时,将不会调用模板复制构造函数。
问题不在于您的复制构造函数模板不匹配。 问题是隐式复制构造函数不是函数模板,并且在涉及重载解析时,非模板优先于模板特化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.