さまざまなコンストラクターは、暗黙的に生成されたものを隠すことになっていますか?
-
22-10-2019 - |
質問
さまざまなコンストラクターは、暗黙的に生成されたもの、つまりデフォルトのコンストラクターとコピーコンストラクターを隠すことになっていますか?
struct Foo
{
template<typename... Args> Foo(Args&&... x)
{
std::cout << "inside the variadic constructor\n";
}
};
int main()
{
Foo a;
Foo b(a);
}
どういうわけか、私はこれが読んだ後に何も印刷しないと思っていました この答え, 、しかしそれは印刷します inside the variadic constructor
G ++ 4.5.0で2回:(この動作は正しいですか?
また、変形テンプレートなしで発生します。
struct Foo
{
Foo()
{
std::cout << "inside the nullary constructor\n";
}
template<typename A> Foo(A&& x)
{
std::cout << "inside the unary constructor\n";
}
};
int main()
{
Foo a;
Foo b(a);
}
繰り返しますが、両方の線が印刷されます。
解決
暗黙的に宣言されたコピーコンストラクターの宣言は、実際には抑制されていません。過負荷解像度のルールのために、それはただ呼ばれていません。
暗黙的に宣言されたコピーコンストラクターにはフォームがあります Foo(const Foo&)
. 。これの重要な部分は、constリファレンスが必要なことです。コンストラクターテンプレートは、コンスト以外の参照を取得します。
a
constではないため、非constユーザーが決定するコンストラクターテンプレートは、暗黙的に決定されたコピーコンストラクターよりも推奨されます。暗黙的に宣言されたコピーコンストラクターを呼び出すには、作成できます a
const:
const Foo a;
Foo b(a);
または使用することができます static_cast
次のconst参照を取得します a
:
Foo a;
Foo b(static_cast<const Foo&>(a));
これを説明する過負荷解像度ルールは、主にC ++ 0x FCDの§13.3.2/3にあります。この特定のシナリオは、LValueとRValueの参照を組み合わせたもので、303ページのさまざまな例で説明されています。
バリアードコンストラクターテンプレートは、バリアードコンストラクターテンプレートがユーザー宣言されており、暗黙的に宣言されたデフォルトコンストラクターがユーザーが推定されているコンストラクターがいない場合にのみ提供されるため、暗黙的に宣言されたデフォルトコンストラクターを抑制します。
クラスにユーザーが宣言したコンストラクターがない場合
X
, 、パラメーターを持たないコンストラクターは、デフォルトとして暗黙的に宣言されます。
バリアードコンストラクターテンプレートは、非テンプレートコンストラクターのみがコピーコンストラクター(C ++ 0xFCD§12.8/2、3、および8)になることができるため、暗黙的に宣言されたコピーコンストラクターを抑制しません。
クラスの非テンプレートコンストラクター
X
最初のパラメーターがタイプの場合、コピーコンストラクターですX&
,const X&
,volatile X&
またconst volatile X&
, 、そして、他のパラメーターがないか、他のすべてのパラメーターにデフォルトの引数があります。クラスの非テンプレートコンストラクター
X
最初のパラメーターがタイプの場合、移動コンストラクターですX&&
,const X&&
,volatile X&&
, 、 またconst volatile X&&
, 、そして、他のパラメーターがないか、他のすべてのパラメーターにデフォルトの引数があります。クラスの定義がコピーコンストラクターを明示的に宣言しておらず、ユーザーが宣言したMOVEコンストラクターがない場合、コピーコンストラクターはデフォルトで暗黙的に宣言されます。