[英]Fill a C++ array with numbers according to a pattern
我有一个要填充数组的模式:
偶数索引值 = -1
奇数索引值 = 1
我目前是这样实现的:
#include <array>
#include <algorithm>
using namespace std;
int generator(){
static int i = 1;
i *= -1;
return i;
}
std::array<int ,64> arr;
std::generate(arr.begin(), arr.end(), generator);
编辑:当前实现有一个警告 - generator
的返回值不依赖于迭代的 object 索引。
有没有办法将当前索引传递给generator
function 所以它的 output 将取决于这个索引?
您的generator
function 有一个static
局部变量,它在每次调用中保留其 state。 这意味着如果您在不同的调用中使用generator
,它会记住它的旧 state,这可能不是您想要的。
您可以通过编写 function 来解决此问题,每次调用它时都会为您提供一个“生成器”。 请注意,返回的值(即生成器本身)只是一个mutable
的 lambda,因此i
的值在多次调用该 lambda 时被保留。
auto gen()
{
return [i = -1]() mutable
{
i *= -1;
return i;
};
}
// usage ...
std::generate(arr.begin(), arr.end(), gen());
这是一个演示。
正如@cigen 所指出的,您的代码按照编写的方式工作。
但是要尝试回答您的问题,“有没有办法将当前索引传递给生成器 function?” - 答案是“不,不是std::generate
”。 这是该调用的示例实现(取自CppReference :
template<class ForwardIt, class Generator>
void generate(ForwardIt first, ForwardIt last, Generator g)
{
while (first != last) {
*first++ = g();
}
}
注意事项:
generate
的这个实现不使用索引,因此它不能将它们传递给生成器。所有的解决方案都假设您的生成器将被顺序调用,那么并行和无序执行呢?
std::array<int, 64> arr;
std::iota(arr.begin(), arr.end(), 0);
std::transform(arr.begin(), arr.end(), arr.begin(), [](auto const i){return i % 2: -1 : 1;});
您想使用错误的 function。 如果元素索引是生成器的参数,则std::transform()
更适合您的要求。
编辑:您需要 c++20 来获得权威的解决方案:
std::array<int, 64> arr;
auto const g(std::views::iota(decltype(arr)::size_type{}, arr.size()));
std::transform(g.begin(), g.end(), arr.begin(), [](auto const i){return i % 2 ? -1 : 1;});
或者:
std::array<int, 64> arr;
std::ranges::copy(std::views::iota(decltype(arr)::size_type{}, arr.size()) | std::views::transform([](auto const i){return i % 2 ? -1 : 1;}), arr.begin());
您可以并行和/或乱序运行它,并且可能还有其他解决方案。
If you want to attach state to a function it is better to use a function object rather than function local static variables (for the very reason you discovered: reusability).
struct generator2 {
bool even = true;
int operator()(){
even = !even;
return even ? -1 : 1;
}
};
int main() {
std::array<int ,64> arr;
std::generate(arr.begin(), arr.end(), generator2{});
for (auto e : arr) std::cout << e;
}
这里传递给std::generate
的是一个generator2
类型的实例,它的operator()
将被调用。
有没有办法将当前索引传递给生成器 function?
std::generate
的生成器必须可以在没有参数的情况下调用:
function 的签名应该等同于以下内容:
Ret fun();
Ret 类型必须使得 ForwardIt 类型的 object 可以被取消引用并分配一个 Ret 类型的值。
仅仅因为std::generate
很难做到并不意味着它不能做到。 您可以编写自己的generate
版本:
namespace mystl {
template<class ForwardIt, class Generator>
void generate(ForwardIt first, ForwardIt last, Generator g)
{
int idx = 0;
while (first != last) {
*first++ = g(idx++);
}
}
}
不受标准算法的限制; 标准库中的大多数都没有什么神奇之处。 不要害怕自己写!
您不能使用std::generate
将当前索引传递给generator
function 。 但是您可以使用lambda来做到这一点:
std::array<int ,64> arr;
auto generator = [i = 1, n = 0] () mutable {
// n is the current index here
i = -i;
n++;
return i;
};
std::generate(arr.begin(), arr.end(), generator);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.