あなたの質問へのコメントで述べたように、あなたの最初の解決策は合理的だと思います。ただし、パラメータを に与えることbegin
が、2 つのケースを区別するための最良の方法であるかどうかはわかりません。これに関する主な問題は、完全なコレクション (localhost メンバーを含む) を範囲として使用できないことです。つまり、Boost.Range アルゴリズムまたは C++11 の範囲ベースの for ループを使用できません。
簡単な解決策は、適切な範囲を返す 2 つの異なるメンバー関数をイテレータのペアとして持つことです。Boost.Range はsub_range
classを提供しますが、これはかなり適切と思われます (メンバーのリストのサブ範囲を返したい場合)。このアプローチを使用したサンプル コードを次に示します。
#include <boost/range.hpp>
#include <iostream>
#include <string>
#include <vector>
struct MemberInfo
{
std::string name;
};
class MemberList
{
public:
typedef std::vector<MemberInfo>::iterator iterator;
typedef std::vector<MemberInfo>::const_iterator const_iterator;
MemberList()
: members_{MemberInfo{"local"}, MemberInfo{"foo"}, MemberInfo{"bar"}}
{}
boost::sub_range<std::vector<MemberInfo>> all() // includes localhost
{
return boost::sub_range<std::vector<MemberInfo>>(
members_.begin(), members_.end());
}
boost::sub_range<std::vector<MemberInfo> const> all() const
{
return boost::sub_range<std::vector<MemberInfo> const>(
members_.begin(), members_.end());
}
boost::sub_range<std::vector<MemberInfo>> some() // excludes localhost
{
return boost::sub_range<std::vector<MemberInfo>>(
++members_.begin(), members_.end());
}
boost::sub_range<std::vector<MemberInfo> const> some() const
{
return boost::sub_range<std::vector<MemberInfo> const>(
++members_.begin(), members_.end());
}
private:
std::vector<MemberInfo> members_;
};
これで、含めるかどうかに応じてall()
またはのいずれかを使用でき、両方を範囲として使用できます。some()
local
int main()
{
MemberList ml;
for (MemberInfo mi : ml.all()) { std::cout << mi.name << '\n'; }
for (MemberInfo mi : ml.some()) { std::cout << mi.name << '\n'; }
}
そしてもちろん、通常どおりイテレータを使用できます。
std::find_if(ml.all().begin(), ml.all().end(), ...);
メンバーが に格納されているという事実を漏らしたくない場合はstd::vector
、 を使用できますany_range
。これにより、基になる反復子の型が消去されます。