C++ 填写C++;根据模式使用数字数组
我有一个填充数组的模式: 偶数指数值=-1 奇数指数值=1 我现在是这样实现的:C++ 填写C++;根据模式使用数字数组,c++,lambda,c++17,C++,Lambda,C++17,我有一个填充数组的模式: 偶数指数值=-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(),
#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);
#包括
#包括
使用名称空间std;
int生成器(){
静态int i=1;
i*=-1;
返回i;
}
std::阵列arr;
std::generate(arr.begin()、arr.end()、generator);
编辑:当前实现有一个警告-返回值generator
不依赖于迭代的对象索引
是否有办法将当前索引传递给
生成器
函数,使其输出取决于此索引?正如@cigen所指出的,您的代码按编写的那样工作
但要回答您的问题,“有没有办法将当前索引传递给生成器函数?”——答案是“没有,不是使用std::generate
”。下面是该调用的示例实现(取自:
模板
void generate(ForwardIt first,ForwardIt last,Generator g)
{
while(第一个!=最后一个){
*第一个+++=g();
}
}
注意事项:
的这个实现不使用索引,因此不能将它们传递给生成器generate
- generator函数为空(不带参数),因此generate无法通过索引,即使它有索引
您的
generator
函数有一个static
局部变量,该变量在每次调用中都保留其状态。这意味着如果在不同的调用中使用generator
,它会记住其旧状态,这可能不是您想要的
您可以通过编写一个函数来修复此问题,该函数在每次调用时都会为您提供一个“生成器”。请注意,返回值(即生成器本身)只是一个mutable
lambda,因此i
的值会在多次调用该lambda时保留
auto gen()
{
return [i = -1]() mutable
{
i *= -1;
return i;
};
}
// usage ...
std::generate(arr.begin(), arr.end(), gen());
这里有一个。您不能使用
std::generate
将当前索引传递给生成器
函数。
但您可以使用lambda来执行此操作:
std::数组arr;
自动生成器=[i=1,n=0]()可变{
//n是这里的当前索引
i=-i;
n++;
返回i;
};
std::generate(arr.begin()、arr.end()、generator);
所有解决方案都假定生成器将按顺序调用,那么并行和无序执行又如何呢
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;});
或:
std::数组arr;
std::ranges::copy(std::views::iota(decltype(arr)::size_type{},arr.size())| std::views::transform([](自动常量i){返回i%2?-1:1;}),arr.begin());
您可以并行和/或无序运行此操作,也可能有其他解决方案。仅仅因为难以使用
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++);
}
}
}
名称空间mystl{
模板
void generate(ForwardIt first,ForwardIt last,Generator g)
{
int-idx=0;
while(第一个!=最后一个){
*第一+++=g(idx++);
}
}
}
不要受标准算法的限制;标准库中的大多数算法都没有什么神奇之处。不要害怕编写自己的算法!你所说的“将当前索引传递给生成器”到底是什么意思??这段代码似乎已经实现了你想要的功能(除了奇数索引为1,偶数索引为-1)。你是在问如何将
生成器
编写为lambda吗?@cigien:我想他的意思是,如果你再次调用它,它可能会失败,因为静态变量没有被重新初始化。所以他想要一个可以多次调用的。你似乎在问如何用参数声明函数。但是为什么?哟你的代码有效,不是吗?你试图解决的问题是什么?请提供一个例子来说明这个问题。@joepol请编辑这个问题并添加你的额外关注点。我相信Nicol Bolas是正确的。一行代码:std::generate(arr.begin(),arr.end(),[v=-1]()可变{return v=-v;};
auto gen()
{
return [i = -1]() mutable
{
i *= -1;
return i;
};
}
// usage ...
std::generate(arr.begin(), arr.end(), gen());
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;});
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());
namespace mystl {
template<class ForwardIt, class Generator>
void generate(ForwardIt first, ForwardIt last, Generator g)
{
int idx = 0;
while (first != last) {
*first++ = g(idx++);
}
}
}