使 std::fill 调用非 const 限定运算符重载

Make std::fill call a non const qualified operator overload

我试图用数字 1 - 100 填充一个数组。我用了std::fill。现在,std::fill 的最后一个参数是填充范围的数字。我想我可以聪明一点,传入一个具有 int 重载的对象,因此当它分配范围元素时,它也会自动增加对象中的数字。

class AutoInc {

public:

    operator int() {
        number++;
        return number - 1;
    }

    int number = 1;

};

... 以及对 std::fill 的以下调用:

int numbers[100];
std::fill(numbers, numbers + 99, (AutoInc());

它抛出一个错误,说它找不到 AutoInc 的 int 重载。这是因为 std::fill 采用常量引用,并且因为 int 重载不是常量,所以它不会调用它。当我将重载更改为 const qualified 并且我不修改 number 时,程序运行(当然没有正确填充数组)。有没有解决的办法?我知道我可以使用 for 循环来填充数组,但我说的是其他采用常量引用的 STL 函数。

您可以使用的一个选项是将 number 限定为 mutable

mutable int number = 1;

那么你可以使用:

operator int() const {
    return number++;
}

但是,正如评论中所建议的那样,您最好使用 std::iota

如果您的问题真的是关于是否可以强制 STL 算法对通过 const 引用传递的对象调用非 const 成员函数,答案很简单,您不能。

一种解决方法是将 number 标记为 mutable 成员。然后 const 成员函数将被允许修改它。

但是,我建议你在做这种事情之前要仔细考虑。该函数采用 const 引用可能是有充分理由的。在 std::fill 的情况下,标准实际上没有指定范围必须以任何特定顺序填充。如果你传入的东西每次调用时都会产生不同的 int 值,那么就不能保证你会得到 1 2 3 4 ...但是如果你传入的东西不使用任何技巧,比如这样,那么不管顺序是什么,你总是得到相同的结果。

正如我在评论中指出的那样,std::iota 是您在这种情况下应该使用的。在更一般的情况下,您需要 std::generate,它通过调用按值传递的函数对象来填充一个范围。