检查shared_ptr的容器是否包含指针
Check if container of shared_ptr contains a pointer?
使用观察者模式。我有一个类,例如称为Monitor,它监视对象的集合。类是一个Observer,其集合中的每个对象都是一个Subject。目前,该集合是作为shared_ptr的std::列表实现的。在Monitor类的Update方法中,我想检查更新是否来自其集合中的一个对象。
std::list<SomeSharedPointer> items_;
...
void Monitor::Update(Subject *subject)
{
if(subject == something_)
{
DoSomething();
}
else if
??
// if subject is one of the objects in our collection then do something..
}
主题这里是一个原始指针和我的集合是一个列表的shared_ptr。我如何有效地检查进入的主题是否属于我收藏的任何一件物品?
(注意我的编译器,msvc,支持lambdas,如果有一个算法解决方案需要一个)
我应该补充一下,我意识到我可以在容器上使用for循环,但我想知道是否有更时髦的方法。
更新2
SomeSharedPointer
是std::shared_ptr<SomeType>
的类型定义,其中SomeType
派生自抽象类Subject
(标准观察者模式实现)。SomeType将在某个时刻调用Notify()
,这将为每个观察者调用Update()
方法。
auto i = std::find_if(items_.begin(), items_.end(),
[=](const SomeSharedPointer& x) { return x.get() == subject; });
if (i != c.end())
{
// Object found, and i is an iterator pointing to it
}
一个小的辅助方法可以使它更可读:
typedef std::list<SomeSharedPtr> ObserverCollection;
// You can also add a const version if needed
ObserverCollection::iterator find_observer(Subject* s)
{
return std::find_if(items_.begin(), items_.end(),
[=](const SomeSharedPointer& x) { return x.get() == s; });
}
然后,如果需要迭代器
,可以这样使用它auto i = find_observer(subject);
if (i != items_.end())
{
// Object found
}
如果你不喜欢,就像这样:
if (find_observer(subject) != items_.end())
{
...
}
如果c++ 11不支持auto,请使用传统方式声明迭代器
for (auto iter = items_.begin(); iter != items_.end(); ++iter)
{
if (subject == iter->get())
{
.. do stuff ..
}
}
共享指针有.get()函数返回指针
既然你说观察者需要根据它正在监控的项目的状态做出决定,那么你应该向基类(你的问题中的Subject
)添加一个方法,它返回一个定义项目状态的enum。然后根据状态,在更新方法中添加一个开关:
enum State{ STATE_1, STATE_2 };
void Monitor::Update(Subject *subject)
{
switch( subject->getState() )
{
case STATE_1:
// do something 1
break;
case STATE_2:
// do something 2
break;
default:
//error
}
}
如果可能的话,您可以考虑将容器更改为能够提供更好的搜索行为的容器。例如,您可以使用std::set
。每次插入的成本更高,但每次查找的速度更快。或者,std::unordered_set
。插入和查找都很快,但迭代可能较慢。为了实现适当的比较,您可以创建一个helper类,以便将原始指针转换为具有无操作删除器的共享指针。
template <typename T>
struct unshared_ptr {
std::shared_ptr<T> p_;
unshared_ptr (T *p) : p_(p, [](...){}) {}
operator const std::shared_ptr<T> & () const { return p_; }
operator T * () const { return p_.get(); }
};
如果您的容器支持find
方法,则:
typedef unshared_ptr<SomeType> unshared_some;
if (items_.end() != items_.find(unshared_some(subject))) {
DoSomething();
}
上网试试!
如果你坚持使用std::list
,你可以通过传递一个总是返回false的谓词来滥用remove_if
方法,但是执行你的匹配测试。
bool matched = false;
auto pred = [subject, &matched](SomeSharedPtr &v) -> bool {
if (!matched && v.get() == subject) {
matched = true;
}
return false;
};
items_.remove_if(pred);
if (matched) {
DoSomething();
} //...
- C++-字符串是否包含一个带有简单循环的单词
- 表达式 SFINAE:如何根据类型是否包含具有一个或多个参数的函数来选择模板版本
- 检查一个数组是否包含在另一个数组中,以相反的顺序,至少两次
- 检查路径是否包含C++中的另一个路径
- C++17:使用 std::optional 来评估枚举是否包含值
- 如何检查 int 变量是否包含合法(非陷阱表示)值?
- 如何确定integer_sequence在编译时是否包含给定的数字?
- 使用预处理指令检查是否包含标头?
- 有没有办法搜索向量的元素,<String>然后检查它是否包含特定的字符,如果它确实打印了它
- 尝试使用 indexOf 创建一个 if 语句来检查字符串是否包含字符.有一点麻烦
- 如何检查字符串是否包含所有这些:数字、字母和特殊字符
- 在Rcpp(和RcppArmadillo)中,如何检查vec是否包含复数
- 使用按位运算确定值是否包含另一个值
- 如何检查一个字符串是否包含多个其他字符串?
- 如何检查联合是否包含类型(使用 type_traits)?
- Djinni 记录是否包含可选的接口字段
- 如何检查数组是否包含多个元素?
- 如何检查每个头文件是否包含必需的包含文件?
- 查找字符串是否包含字符串向量的任何一个元素的最佳方法
- VTBL 是否包含指向非虚函数的指针?