对std :: forward_list :: remove_if谓词

时间:2017-07-07 07:40:51

标签: c++ list c++11 language-lawyer predicate

考虑以下代码:

struct T
{
bool status;
UsefulData data;
};

std::forward_list<T> lst;

lst.remove_if([](T &x) -> bool { return x.status= !x.status; });

即。切换状态并一次性删除非活动元素。

根据cppreference,上面的代码似乎是未定义的行为(强调我的):

template< class UnaryPredicate >
void remove_if( UnaryPredicate p );
     

p - 一元谓词,如果要删除该元素,则返回true。   谓词函数的签名应等同于以下内容:

bool pred(const Type &a);
     

签名不需要const &,但函数不能修改传递给它的对象。   类型Type必须使forward_list<T,Allocator>::const_iterator类型的对象可以取消引用,然后隐式转换为Type

但是,目前的工作草案似乎限制性较小(N4659 [forwardlist.ops]):

void remove(const T& value)
template <class Predicate> void remove_if(Predicate pred);
     

效果:

     

删除列表迭代器i引用的列表中的所有元素,其中包含以下条件:*i == value(对于remove()),pred(*i)为{{1 (true)。仅使迭代器和对已擦除元素的引用无效。

     

抛出:

     

除非等式比较或谓词抛出异常,否则无效。

     

说明:

     

稳定(20.5.5.7)。

     

复杂度:

     

相应谓词的remove_if()个应用程序。

标准的其他部分对谓词还有其他限制吗?

我已经在许多编译器上测试了上面的代码,它编译并且似乎按预期工作。我真的需要横向列表两次吗?

2 个答案:

答案 0 :(得分:2)

根据您提出的意见,我的观点是:

  • forward_list::remove_if不是算法,因此不属于[algorithms.requirements]的规则。

  • [forwardlist.ops]对谓词中的内容没有限制。

  • forward_list::remove_if需要在范围内的每个项目中恰好应用一次谓词。

因此,在这种情况下修改谓词中的对象是严格合法的,如果有点反社会的话。

编辑:

根据T.C.后来的回答,长期不合法...... https://stackoverflow.com/a/45052149/2015579

答案 1 :(得分:2)

The committee's Library Working Group has just moved LWG issue 2998 to "Ready" status, essentially confirming that the committee's intent here is that the relevant requirements from Clause 28 (the algorithms clause) apply to the similar list operations. This includes the requirement that the Predicate does not apply any non-constant functions.

Once the issue resolution is adopted (which should happen at the next committee meeting), the code in the OP will formally have undefined behavior. Nonetheless, it should generally work as desired barring an intentionally hostile implementation. If an implementation with guaranteed well-defined behavior is desired, it's not too hard to write one manually with iterators and erase_after.