[解決済み】パブリックフレンドスワップメンバー関数
質問
の美しい答えの中に コピーアンドスワップイディオム があるのですが、ちょっと助けて欲しいコードがあります。
class dumb_array
{
public:
// ...
friend void swap(dumb_array& first, dumb_array& second) // nothrow
{
using std::swap;
swap(first.mSize, second.mSize);
swap(first.mArray, second.mArray);
}
// ...
};
そして、彼はメモを追加します。
他にも、std::swap を私たちの型に特化させるべき、自由関数の swap と共にクラス内 swap を提供すべき、などの主張があります。swapの適切な使用は非限定呼び出しによるものであり、我々の関数はADLによって発見されるのである。一つの関数で十分なのだ。
と
friend
私は、正直言って、少し不親切な条件です。そこで、主な質問をします。
- フリーファンクションに見える しかし、それはクラスボディの中にあるのですか?
-
なぜ、この
swap
静的 ? 明らかにメンバ変数を使用していません。 -
swapの適切な使用は、ADLを介してswapを見つけることができます。
? ADLは名前空間を検索しますよね?でも、クラスの中も調べるのでしょうか?それとも、ここで
friend
が入ってくるのでしょうか?
サイドクエスチョン
-
C++11では
swap
を使用しています。noexcept
? -
C++11とその
レンジフォー
を配置する必要があります。
friend iter begin()
とfriend iter end()
は、クラス内でも同じように使えるのでしょうか?私はfriend
はここでは必要ありませんよね?
どのように解決するのですか?
を記述する方法はいくつかあります。
swap
その中には、他のものより優れているものもあります。しかし、時が経つにつれて、一つの定義が最も効果的であることが分かってきた。では、このような場合、どのように考えればよいのでしょうか。
swap
という関数があります。
のようなコンテナがあることを最初に確認します。
std::vector<>
は、単一引数のメンバ関数
swap
のようなものです。
struct vector
{
void swap(vector&) { /* swap members */ }
};
当然、私たちのクラスもそうでなければなりませんね?でも、そうでもないんです。標準ライブラリには
不要なものばかり
というメンバー
swap
はその一つです。なぜ?続けてみましょう。
私たちがすべきことは、何がカノニカルなのか、そして私たちのクラスの
が必要です。
と連携するために必要です。そしてスワッピングの正統的な方法は
std::swap
. メンバ関数が役に立たないのはこのためです。メンバ関数は、一般的に物事を交換する方法ではなく、また
std::swap
.
さて、では
std::swap
を提供する必要があります(そして
std::vector<>
の特殊化を提供すべきであった。
std::swap
ということですね?
namespace std
{
template <> // important! specialization in std is OK, overloading is UB
void swap(myclass&, myclass&)
{
// swap
}
}
この場合、確かにうまくいくのですが、これには重大な問題があります。つまり、テンプレート・クラスをこの方法で特殊化することはできず、特定のインスタンス化のみが可能です。
namespace std
{
template <typename T>
void swap<T>(myclass<T>&, myclass<T>&) // error! no partial specialization
{
// swap
}
}
この方法は、ある時はうまくいきますが、すべての時にうまくいくわけではありません。もっといい方法があるはずです。
ありますよ! を使えばいいんです。
friend
関数を使用して、それを見つけることができます。
ADL
:
namespace xyz
{
struct myclass
{
friend void swap(myclass&, myclass&);
};
}
何かを入れ替えたいときは、以下のように関連付けます。
†
std::swap
というように、非限定的な呼び出しを行います。
using std::swap; // allow use of std::swap...
swap(x, y); // ...but select overloads, first
// that is, if swap(x, y) finds a better match, via ADL, it
// will use that instead; otherwise it falls back to std::swap
とは何ですか?
friend
関数があります。このあたりは混乱がありますね。
C++が標準化される前。
friend
関数は、フレンド名注入と呼ばれるものを行い、コードは以下のように動作します。
あたかも
その関数が周囲の名前空間に書かれていた場合。例えば、これらは標準以前は同等であった。
struct foo
{
friend void bar()
{
// baz
}
};
// turned into, pre-standard:
struct foo
{
friend void bar();
};
void bar()
{
// baz
}
しかし
ADL
が発明され、これは削除された。その
friend
関数は、その後
のみ
自由な関数として使用したい場合は、そのように宣言する必要があります (
これを見て
といった具合に)。しかし、問題がありました。
を使うだけなら
std::swap(x, y)
を使用すると、オーバーロードは
決して
を探すと明示的に言っているので、見つからないのです。
std
そして、他のどこにもないのです。このため、2つの関数を書くことを提案する人もいました。
エーディエル
を処理するためのもので、もう一つは明示的な
std::
の資格を取得することができます。
しかし、これまで見てきたように、これはすべてのケースでうまくいくわけではなく、結局は醜い混乱を招くことになります。その代わりに、イディオマティックスワップは別の方法をとりました。
std::swap
を使わないようにするのはスワッパーの仕事です。
swap
上記のように そしてこれは、人々がそれを知っている限り、かなりうまくいく傾向があります。しかし、そこに問題があります。非限定的な呼び出しを使う必要があるというのは、直感的ではありません
これを簡単にするために、Boost のようないくつかのライブラリは、関数
boost::swap
への非限定的な呼び出しを行うだけです。
swap
とは異なり
std::swap
を関連する名前空間として使用します。これでまた物事を簡潔にすることができますが、それでも残念なことです。
の動作は、C++11でも変更されていないことに注意してください。
std::swap
と、私や他の人が勘違いしていた。もし、これに食いついたのなら
ここを読む
.
要するに、メンバ関数はただのノイズで、特殊化は醜く、不完全なものだが
friend
関数は完全で、機能します。そしてスワップするときは
boost::swap
または非限定的な
swap
と
std::swap
を連想させる。
†Informally, a name is
関連
は、関数呼び出しの際に考慮される場合。詳しくは、§3.4.2を読んでください。この場合
std::swap
通常は考慮されません。
関連付ける
によって考慮されるオーバーロードのセットに追加されます。
swap
というように、検索されるようになります。
関連
-
[解決済み】getline()が何らかの入力の後に使用されると動作しない 【重複あり
-
[解決済み】C++エラーです。"配列は中括弧で囲まれたイニシャライザーで初期化する必要がある"
-
[解決済み】変数 '' を抽象型 '' と宣言できない。
-
[解決済み】関数名の前に期待されるイニシャライザー
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】標準ライブラリにstd::endlに相当するタブはあるか?
-
[解決済み] コピーアンドスワップ慣用句とは?
-
[解決済み] 私的相続、公的相続、保護相続の違いについて
-
[解決済み] C++で'friend'はいつ使うべきですか?
-
[解決済み】メンバ関数でスレッドを開始する
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++ クラスヘッダが含まれているときに「不明な型」があるのはなぜですか?重複
-
[解決済み】 != と =! の違いと例(C++の場合)
-
[解決済み】C++エラーです。"配列は中括弧で囲まれたイニシャライザーで初期化する必要がある"
-
[解決済み】文字列関数で'char const*'のインスタンスを投げた後に呼び出されるterminate [閉店].
-
[解決済み】'cout'は型名ではない
-
[解決済み】Visual C++で "Debug Assertion failed "の原因となる行を見つける。
-
[解決済み] 式はクラス型を持つ必要があります。
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】変数やフィールドがvoid宣言されている
-
[解決済み] コピーアンドスワップ慣用句とは?