免責事項:衒学的なタイプ (または衒学的になりたい場合は、衒学者) については、ここでは通常、 「過負荷」という言葉を「 andと doという名前を持つ関数を作成する」と呼んでいます。begin
end
using std::begin; using std::end;
、私を信じてください、私が書くのはまったく退屈ではありませんが、読むのは非常に難しく、読むのは冗長です.:p.
基本的に、そのような手法の可能なユースケースを紹介し、後で結論を述べます.
ケース 1 -メソッドbegin
とend
メソッドが標準コンテナーのように機能しない
std::begin
andstd::end
関数をオーバーロードする必要がある状況の 1 つは、オブジェクトの要素への反復子のようなアクセスを提供する以外の別の方法で型のbegin
andメソッドを使用していて、 and のオーバーロードを呼び出したい場合です。反復に使用される begin メソッドと end メソッド。end
std::begin
std::end
struct weird_container {
void begin() { std::cout << "Start annoying user." }
void end() { std::cout << "Stop annoying user." }
iterator iter_begin() { /* return begin iterator */ }
iterator iter_end() { /* return end iterator */ }
};
auto begin(weird_container& c) {
return c.iter_begin();
}
auto end(weird_container& c) {
return c.iter_end();
}
weird_container
ただし、 range-forのルールに従って、のオブジェクトweird_container::begin()
と一緒に使用すると range-for が壊れてしまうようなクレイジーなことを行うべきではありませんweird_container::end()
。
したがって、このケースでは、言語の非常に便利な機能の 1 つが壊れてしまうため、あなたが提案したものを使用しないという議論が生じます。
ケース 2 -begin
メソッドend
がまったく定義されていない
begin
もう 1 つのケースは、 andend
メソッドを定義しない場合です。これは、クラス インターフェイスを変更せずに型を反復可能に拡張する場合に、より一般的で適切なケースです。
struct good_ol_type {
...
some_container& get_data();
...
};
auto begin(good_ol_type& x) {
return x.get_data().begin();
}
auto end(good_ol_type& x) {
return x.get_data().end();
}
good_ol_type
これにより、インターフェイスを実際に変更することなく、いくつかの気の利いた機能 (アルゴリズム、range-for など) を使用できるようになります! これは、非メンバー非フレンド関数を通じて型の機能を拡張するという Herb Sutter の推奨事項と一致しています。
std:;begin
これは良いケースで、実際にandをオーバーロードしたい場合ですstd::end
。
結論
誰かが最初のケースのようなことをするのを見たことがないので(私の例を除いて)、提案したものを使用してオーバーロードstd::begin
し、std::end
適用可能な場合はどこでも使用したいと思うでしょう。
begin
ここでは、 andend
メソッドと、メソッドとは異なることを行うbegin
and関数の両方を定義したケースは含めませんでした。end
このような状況は、デバッガーを掘り下げたり、新しいテンプレートエラーを読んだりした経験があまりないプログラマーによって、不自然で、不適切な形式で、および/または行われたと思います。