0

HTMLページからURLを抽出するC++のクラスを設計しています。私はBoostの正規表現ライブラリを使用して手間のかかる作業を行っています。クラスの設計を始めて、URLの保存方法を制限したくないことに気づきました。1つのオプションは、参照によってを受け入れ、std::vector<Url>それに対してpush_backを呼び出すことです。クラスのコンシューマーにを強制的に使用させないようにしたいと思いますstd::vector。そこで、宛先イテレータを使用するメンバーテンプレートを作成しました。次のようになります。

template <typename TForwardIterator, typename TOutputIterator>
TOutputIterator UrlExtractor::get_urls(
    TForwardIterator begin,
    TForwardIterator end, 
    TOutputIterator dest);

物事を複雑にしすぎているような気がします。私はC++でかなり一般的なコードを書くのが好きで、インターフェイスをロックダウンするのに苦労しています。しかし、それから私はこれらの窮状に陥り、すべてをテンプレート化しようとしています。この時点で、コードを読んでいる人は、それTForwardIteratorがを繰り返していることに気づいていませんstd::string

私の特定の状況では、このジェネリックであることは良いことであるかどうか疑問に思っています。どの時点でコードをより明確にし始めますか?関数から一般的に値を取得するための標準的なアプローチはありますか?

4

4 に答える 4

3

はい、それは素晴らしいだけでなく、とても素敵なデザインです。そのようにテンプレート化することは、またはのような標準ライブラリアルゴリズムのほとんどがどのように機能するstd::fillstd::copyです。これらはイテレータと連携するように作成されているため、すでに要素が含まれているコンテナを埋めることができます。または、を使用して空のコンテナを取得し、データを埋めることができますstd::back_inserter

これは非常に優れた設計IMOであり、テンプレートの能力とイテレーターの概念を利用しています。

あなたはそれをこのように使うことができます(しかしあなたはすでにこれを知っています):

std::list<Url> l;
std::vector<Url> v;

x.get_urls(begin(dat1), end(dat1), std::back_inserter(l));
y.get_urls(begin(dat2), end(dat2), std::back_inserter(v));

テンプレートを使用することを恐れている、「通常の」C ++ではない、またはテンプレートを避けて肥大化するなどの感覚があります。確かに、これらは非常に正常で、他の言語(私が知っている)にはない強力な言語機能であるため、使用するのが適切な場合はいつでも使用してください。そしてここでは、それは非常に適切です。

于 2012-09-25T15:39:48.880 に答える
2

あなたが間違ったインターフェースを持っているように私には見えます。

イテレータからコンテナにコピーするためのアルゴリズムはすでに存在します。あなたのクラスは(ソースの変更に依存せずに)URLのストリームを提供しているように私には思えます。したがって、本当に必要なのは、イテレータ(フォワードイテレータ)を介して内部データを公開する方法だけです。したがって、begin()とend()を提供する必要があります。

UrlExtractor             page(/* Some way of constructing page */);
std::vector<std::string> data;

std::copy(page.begin(), page.end(), std::back_inserter(data));

次のインターフェイスを提供するだけです。

class UrlExtractor
{
    ...... STUFF
    iterator begin(); 
    iterator end();
};
于 2012-09-25T15:54:56.417 に答える
0

はい、あなたはあまりにも一般的です。テンプレートのポイントは、動作が異なる関数の複数のコピーを生成できることです。URLを表す1つの方法を選択し、それをプログラム全体で使用する必要があるため、おそらくそれは望ましくありません。

あなたはどうですか:

typedef std::string url;

これにより、将来URLに使用するクラスを変更できます。

たぶん、その中にstd::vectorいくつかのインターフェースを実装push_back()し、あなたのメソッドはそのインターフェースへの参照を取ることができます(back_inserter?)。

于 2012-09-25T15:28:07.993 に答える
0

実際のユースケースのシナリオを知らずに言うのは難しいですが、一般的に、実際に何かを購入しない限り、テンプレート(またはその他の不要な複雑さ)は避ける方がよいでしょう。ここで最も明白な署名は次のとおりです。

std::vector<Url> UrlExtractor::get_urls( std::string const& source );

何かを解析しなければならない可能性のあるシナリオは本当にありますstd::stringか?(入力イテレータもサポートしている場合もありますが、実際には、解析している場合、ソースはastd::stringまたは。のいずれかになります。std::istream&後者を本当にサポートしたい場合を除いて、使用してstd::stringください。)そしてもちろん、クライアントコードは別のタイプのコレクションに追加するなど、返されたベクトルを使用して必要な処理を行います。

を返すコストが問題になる場合は、引数としてstd::vectorをとることができます。std::vector<Url>&追加の柔軟性があなたに多くを買うだろうという合理的なシナリオを私は見ることができません、そしてのような関数get_urlsはかなり複雑である可能性が高く、あなたがヘッダーに入れたいようなものではありません。

于 2012-09-25T15:51:50.430 に答える