![](/img/trans.png)
[英]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.