使 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
,它通过调用按值传递的函数对象来填充一个范围。
我试图用数字 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
,它通过调用按值传递的函数对象来填充一个范围。