3

サンプル コードは非常に単純なものにするように努めますが、その場で入力しているため、エラーが発生する可能性があります。

Phoneという名前のクラスがあります。

class Phone
{
 public:
  Phone(std::string manufacturer, std::string model, std::vector<Feature> features);

 private:
  std::vector<Features> features;
  std::string model;
  std::string manufacturer;
};

Feature という名前の構造体があります。

struct Feature
{
   Feature(std::string feature, std::string category);
   std::string feature;
   std::string category;
};

ご覧のとおり、電話には機能のリスト (ベクトル) があります。ブルートゥース、GPS、ラジオなど。ネットワーク、ナビゲーション、マルチメディアのカテゴリがあります。

電話と機能に関する情報が sqlite3 データベースに保存されるようになりました。データベースから特定の電話モデルを取得し、入力された Phone オブジェクトを返すヘルパー関数があります。また、Phone オブジェクトを受け取り、Phone をデータベースに書き込む関数もあります。

問題は、電話の機能のリストを反復処理する何らかの方法をクライアントに提供する必要があることです。まず、データベース ヘルパーは、データベースに機能を書き込むことができるように機能について知る必要があります。次に、クライアントはデータベースから電話を取得し、機能のリストをユーザーに表示する必要がある場合があります。

1 つの解決策は、次の関数をクラス Phone に追加することです。

std::vector<Feature>::iterator begin()
std::vector<Feature>::iterator end()

クライアント コードが直感的に見えないため、これは私にとって理想的なソリューションではありません。実際には機能を反復しているときに、クライアントが電話を反復しているように見えます。

http://accu.org/index.php/journals/1527の記事で別の解決策が説明されています。この記事では、 「メンバースペース」という手法を使用してイテレーターをクライアント コードに公開する方法について説明しています。これにより、クライアント コードがより読みやすくなりますが、私の意見では、実装は少し面倒です。

イテレータの問題に対するより良い解決策はありますか、それとも私が使用できるより適切な設計パターンがあるかもしれません。

どんなフィードバックでも大歓迎です。

4

2 に答える 2

1

クライアントコードでBOOST_FOREACHを使用する場合は、メソッドを追加するだけではどうでしょうか。

const std::vector<Feature>& getFeatures() const;

電話する?

于 2010-09-05T07:09:13.457 に答える
1

あなたの場合、私は最初により良い名前を探します:

typedef std::vector<Feature> Features;

Features::iterator features_begin();
Features::iterator features_end();
Features::const_iterator features_begin() const;
Features::const_iterator features_end() const;

例:
1)

 // Note: you'll need to define an operator<< for Feature
 // can be used with std::algorithms
 std::copy( phone.features_begin(), phone.features_end(),
   std::ostream_iterator<Feature>( std::cout, "\n\r" ) );     

2)

// Note: shamelessly borrowed from http://www.boost.org/doc/libs/1_44_0/doc/html/foreach/extensibility.html
// add overloads of range_begin() and range_end() for Phone::Features
inline Phone::Features::iterator range_begin( Phone& phone ){
   return phone.features_begin();
}

inline Phone::Features::iterator range_end( Phone& phone ){
   return phone.features_end();
}

namespace boost{
   // specialize range_mutable_iterator and range_const_iterator in namespace boost
   template<>
   struct range_mutable_iterator< Phone >{
      typedef Phone::Features::iterator type;
   };

   template<>
   struct range_const_iterator< Phone >{
      typedef Phone::Features::const_iterator type;
   };
}
...
// can be used with BOOST_FOREACH
BOOST_FOREACH( Feature x, phone ){
   std::cout << x << std::endl;
}

PS 与えられた Jonannes の提案と、名前で使用される命名規則boost::rangeは現在ではfeatures_xxx()なくxxx_features()(特に、このコンテキストではより意味があるため) です。

于 2010-09-04T01:46:30.340 に答える