我可以使用私有嵌套结构编写仿函数吗?

时间:2010-03-22 15:29:05

标签: c++ nested private functor

鉴于此课程:

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

这里的想法是fooList可以由Foo结构的key1key2索引。我正在尝试编写仿函数以传递给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;
    }
};

6 个答案:

答案 0 :(得分:2)

是。使该仿函数成为C的另一成员,并将std::find_if封装在C的方法后面。

以下是一个例子:

#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;
}

答案 1 :(得分: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.
}

排序......

答案 2 :(得分:1)

您可以将仿函数变为C的朋友。

答案 3 :(得分:1)

语法非常巴洛克式,但我可以将fooList转换为key1key2上的boost::multi_index_container索引。

答案 4 :(得分:0)

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

这会为您留下一个更清晰的标题,不会被实现细节遮挡。

答案 5 :(得分:0)

我可以使用Pimpl Idiom隐藏另一个类中C的私有部分。由于CImpl中的所有内容都可以安全公开,因此我应该能够在Foo处执行任何操作。