鉴于此课程:
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;
}
};
答案 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
转换为key1
和key2
上的boost::multi_index_container
索引。
答案 4 :(得分:0)
如果你的头文件中不需要你的结构,你也可以在实现文件中使用未命名的命名空间来使编译单元的定义和声明本地化(静态是类似C的替代static
)
这会为您留下一个更清晰的标题,不会被实现细节遮挡。
答案 5 :(得分:0)
我可以使用Pimpl Idiom隐藏另一个类中C
的私有部分。由于CImpl
中的所有内容都可以安全公开,因此我应该能够在Foo
处执行任何操作。