【问题标题】:remove_if from a std::vector of shared pointers with a member function从具有成员函数的共享指针的 std::vector 中删除_if
【发布时间】:2017-03-10 16:28:36
【问题描述】:

如何删除满足条件ptile->hasNoRegions()std::vector<std::shared_ptr<PTile>> ptiles 的元素?我一直在尝试为此使用remove_if,但Predicate 使用对象的数据成员,而不是指针。如果元素是指向对象的智能指针,如何将谓词设置为函数?

我现在拥有的东西

    ptiles.erase(std::remove_if(ptiles.begin(), ptiles.end(), &PTile::hasNoRegions), ptiles.end());

其中hasNoRegionsPTile 的成员函数。这显然不起作用,因为我有一个 std::shared_ptr<PTile>,而不是 PTile

我正在使用 MSVC 2013。

【问题讨论】:

  • 元素被其他对象引用,所以它们是共享的。我正在将它们从特定向量中删除,但它们会存活♫。另外,std::unique_ptr 是不可复制的,所以我不能拥有unique_ptrstd::vector,对吗?
  • vector 要求元素是可移动的。也许您只是想传递原始引用或指针?

标签: c++ c++11 smart-pointers idioms


【解决方案1】:

即使向量不存储指针,这也可能不起作用,因为成员函数将this 作为隐式参数,并且不会生成代码。

您需要编写一个能显式处理std::shared_ptr 的函子或lambda。

ptiles.erase(
    std::remove_if(ptiles.begin(), ptiles.end(), [](std::shared_ptr<PTile> const& ptr) {
        return ptr->hasNoRegions();
    }), 
    ptiles.end()
);

替代方案,如果您没有 lambda:

//Outside method
bool should_remove_ptile(std::shared_ptr<PTile> const& ptr)  {
    return ptr->hasNoRegions();
}

//inside method

ptiles.erase(std::remove_if(ptiles.begin(), ptiles.end(), should_remove_ptile), ptiles.end());

【讨论】:

  • 谢谢!我确实有 lambda。 +1 auto 扩展和非 lambda 解决方案。
【解决方案2】:

我一直在尝试为此使用 remove_if,但 Predicate 使用对象的数据成员,而不是指针。

什么指针?您将需要使用 lambda,因为不支持传递成员函数指针:

ptiles.erase(std::remove_if(ptiles.begin(), ptiles.end(), [](const auto& value) {
    return value->hasNoRegions();
}), ptiles.end());

请注意,MSVC 2013 对现代 C++ 的支持很差,因此您可能需要编写函子而不是 lambda,或者不要在 lambda 中使用 auto

【讨论】:

  • “在 C++17 中,您的代码应该可以正常编译,因为 std::invoke。” 这对我来说是个新闻 - 来源?我试过了,但它does not compile neither on g++7 nor on clang++5
  • 好的,我将使用 lambdas。你的例子对我来说很清楚。 (顺便说一句,我以为是 MSVC 2012,但它是 2013)
  • @VittorioRomeo 我错误地认为std::invoke 将用于算法,但事实并非如此:see this section。谢谢!
猜你喜欢
  • 1970-01-01
  • 2013-06-11
  • 1970-01-01
  • 2012-03-18
  • 1970-01-01
  • 1970-01-01
  • 2010-12-27
  • 2013-04-02
  • 2017-11-13
相关资源
最近更新 更多