不能将 std::iota 与 std::set 一起使用

Cannot use std::iota with std::set

本文关键字:std 一起 set iota 不能      更新时间:2023-10-16

我想创建一组数字范围:0、1、2、3、4、...以下代码编译失败:

std::set<int> s;
std::iota(s.begin(), s.end(), 0);

出现以下错误消息:

error C3892: '_First' : you cannot assign to a variable that is const

编译器是VC++2012。相同的代码适用于向量。我应该如何将其与套装一起使用?

更新

我现在可以看到我的代码毫无意义,因为没有指定设置大小。

以下是有关我的问题的更多详细信息。

我有一个集合包含 [0, N] 范围内的一些数字。在我的应用程序中,我需要多次计算此类集合的集合差值。N 是固定的。

假设N = 5,第一组是s1 = {0, 3, 4}.我需要计算集合差{0, 1, 2, 3, 4} {0, 3, 4} == {1, 2}。对于不同的集合,应该经常执行此操作,因此我认为我可以创建一个包含所有数字的集合(在这种情况下{0, 1, 2, 3, 4})并使用std::set_difference来计算这些差异。

要解决您的实际问题:std::set_differencestd::set的关系比您预期的要小。您可以使用任何一对迭代器作为set_difference的前两个参数,前提是它们按顺序返回值。作为一个集合没有特别的好处。

因此,例如包含值 0 的std::vector的开始/结束迭代器...n-1 按顺序工作,或一对boost::counting_iterator

std::set result;
std::set_difference(
    boost::counting_iterator<int>(0), boost::counting_iterator<int>(n),
    s1.begin(), s1.end(),
    std::inserter(result, result.end())
);

输出也不需要是集合,您也可以使用带有back_insertervector

为了解决你的问题:尝试在片场使用iota是没有意义的。 iota通过为范围中包含的值分配新值来更改这些值。不能分配给set中的值。

如果你想要一个包含数字的集合 0 ... n-1 ,则:

std::set<int> s;
for (int i = 0; i < n; ++i) {
    s.insert(s.end(), i);
}

如果有人告诉你循环是用于 wusses 的,而真正的C++程序员使用算法,那么如果你真的想要,你可以参与iota

std::set<int> s;
{
    std::vector<int> vec(n);
    std::iota(vec.begin(), vec.end(), 0);
    s.insert(vec.begin(), vec.end());
}

不幸的是,这有点低效。因此,如果你非常喜欢算法,以至于你不妨将它们结合起来,那么你可以超越标准库:

std::set<int> s(boost::counting_iterator<int>(0), boost::counting_iterator<int>(n));

一个有点不优雅的选择:

set<int> s;
generate_n(inserter(s, s.end()), 10, [&]{ return s.size(); });

集合与向量的不同之处在于,向量具有从索引到存储在该索引处的值的关联,而集合仅包含值是否在集合中的信息。 因此,将值分配给 set 元素是荒谬的——强制执行它的方法是集合中的元素是恒定的。

等效的方法是删除集合中不需要的值(向量情况下为"旧"值),然后遍历要存储的值(使用 itoa 它将是一系列递增的值)并将它们逐个添加到集合中。