1

我有一个类 memberlist,其中包含一个类成员std::list信息。这些代表网络上的对等点。

我使用该类向列表中添加一些功能。

我想公开一些迭代器(开始和结束),以便外部代码可以遍历我的内部列表并读取它们的数据。但是,我想有两种方法来做到这一点 - 一种包含 localhost 的元素,另一种不包含。

有什么好方法可以做到这一点?

我可以先放置本地节点,然后begin(showlocal=false)只给出第二个元素而不是第一个。或者有人建议用布尔值存储一对,说明它是否是本地的。

关于这样做的好方法有什么建议吗?我对高级的STL东西还不太了解。

4

2 回答 2

4

就我个人而言,我会以不同的方式处理这个问题,让你memberinfo有办法告诉你它是否是本地的。

这样,由于包含对象的专门化,您不会专门化您的集合类。实际上,您可以只使用标准std::list<memberinfo>.

例如

class memberinfo
{
    bool IsLocal( ) const;
}

然后,您将在迭代包含的对象时选择是否对本地成员感兴趣。

例如

std::list<memberinfo>::iterator it;
std::list<memberinfo> list;

for ( it = list.begin() ; it != list.end() ; it++ )
{
    if ( it->IsLocal() )
    { 
        // blah blah blah
    }
    else
    {
        // dum dee dum dee
    }
}
于 2012-09-14T14:47:38.743 回答
0

正如我在评论您的问题时所说,我认为您的第一个解决方案是合理的。但是,我不确定提供参数 tobegin是区分这两种情况的最佳方法。这样做的主要问题是您不能将完整集合(包括 localhost 成员)用作范围,这意味着您不能使用Boost.Range 算法或基于 C++11 范围的 for 循环。

一个简单的解决方案是让两个不同的成员函数返回适当的范围,作为一对迭代器。Boost.Range 提供了一个sub_rangeclass,这似乎很合适(您想返回成员列表的子范围)。这是使用这种方法的示例代码:

#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(), ...);

如果您不想泄露成员存储在 a 中的事实,则std::vector可以使用any_range,它会擦除​​底层迭代器类型。

于 2012-09-14T16:09:29.050 回答