5

给定这个类:

class C
{
    private:
        struct Foo
        {
            int key1, key2, value;
        };
        std::vector<Foo> fooList;
};

这里的想法是fooList可以由Foo 结构中的一个key1或一个来索引。key2我正在尝试编写要传递给的函子,以便我可以按每个键std::find_if查找项目。fooList但我无法让它们编译,因为Foo在类中是私有的(它不是 C 接口的一部分)。 有没有办法在不暴露Foo于世界其他地方的情况下做到这一点?

这是一个无法编译的代码示例,因为Foo在我的类中是私有的:

struct MatchKey1 : public std::unary_function<Foo, bool>
{
    int key;
    MatchKey1(int k) : key(k) {}
    bool operator()(const Foo& elem) const
    {
        return key == elem.key1;
    }
};
4

6 回答 6

2

是的。使函子成为另一个成员C并封装std::find_ifC.

下面是一个例子:

#include "stdafx.h"
#include <vector>
#include <cassert>
#include <algorithm>
#include <iostream>

class C
{
    private:
        struct Foo
        {
            int key1, key2, value;
        };

        std::vector<Foo> fooList;

    struct Finder
    {
    private:
      int key1, key2;

    public:
      Finder(int k1, int k2)
      {
        key1 = k1;
        key2 = k2;
      }

      bool operator ()(Foo const& foo) const
      {
        return foo.key1 == key1 || foo.key2 == key2;
      }
    };

public:
  C()
  {
    Foo foo1, foo2;
    foo1.key1 = 5;
    foo1.key2 = 6;
    foo1.value = 1;
    foo2.key1 = 7;
    foo2.key2 = 8;
    foo2.value = 10;

    fooList.insert(fooList.begin(), foo1);
    fooList.insert(fooList.begin(), foo2);
  }

  int Find(int key1, int key2)
  {
    return std::find_if(fooList.begin(), fooList.end(), Finder(key1, key2))->value;
  }
};

int _tmain(int argc, _TCHAR* argv[])
{
  C c;

  std::cout << c.Find(5, 3) << std::endl;
  std::cout << c.Find(3, 6) << std::endl;
  std::cout << c.Find(7, 3) << std::endl;
  std::cout << c.Find(3, 8) << std::endl;

  return 0;
}
于 2010-03-22T15:38:46.173 回答
2

我会做这样的事情。

标题:

class C
{
private:
    struct Foo
    {
        int index;
        Bar bar;
    };

    // Predicates used to find Notification instances.
    struct EqualIndex;
    struct EqualBar;

    std::vector<Foo> fooList;
};

来源:

// Predicate for finding a Foo instance by index.
struct C::EqualIndex : std::unary_function<C::Foo, bool>
{
    EqualIndex(int index) : index(index) { }
    bool operator()(const C::Foo& foo) const { return foo.index == index; }
    const int index;
};

// Predicate for finding a Foo instance by Bar.
struct C::EqualBar : std::unary_function<C::Foo, bool>
{
    EqualBar(const Bar& bar) : bar(bar) { }
    bool operator()(const C::Foo& foo) const { return foo.bar == bar; }
    const Bar& bar;
};

用法:

// Find the element containing the Bar instance someBar.
std::vector<Foo>::iterator it = std::find_if(fooList.begin(),
                                             fooList.end(),
                                             EqualBar(someBar));

if (it != fooList.end())
{
    // Found it.
}

有点...

于 2010-03-22T15:54:24.970 回答
1

你可以让函子成为 的朋友C

于 2010-03-22T15:33:32.057 回答
1

语法非常巴洛克,但我可以fooList变成一个boost::multi_index_container索引 on key1and key2

于 2010-03-22T15:57:30.240 回答
0

如果你不需要你的头文件中的结构,你也可以在你的实现文件中使用未命名的命名空间来使编译单元的定义和声明成为本地的(静态是类 C 的替代方案static)。

这为您留下了一个更清晰的标题,不会被实现细节所掩盖。

于 2010-03-22T16:05:07.613 回答
0

我可以使用Pimpl Idiom来隐藏C另一个类中的私有部分。既然里面的所有东西都CImpl可以安全地公开,我应该可以在那里做任何我想做的事情Foo

于 2010-03-22T16:31:03.667 回答