通过STL或Boost引入伪参数

时间:2011-05-03 18:20:44

标签: c++ boost stl

假设有人想用随机数填充向量。然后有一个明显的解决方案:

vector<int> result;
result.resize(n);
for (int i = 0; i < n; ++i) {
    result[i] = generateRandomNumber();
}

好吧,它显然有效,但我想了解什么是最简单的STL / Boost摆脱for循环的方法。使用std :: transform很有吸引力,但它需要一个带有一个参数的函数。有没有很好的STL方法在函数中引入伪参数?

3 个答案:

答案 0 :(得分:5)

C ++标准库包含std::generate()std::generate_n();

例如:

#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <iterator>
int generateRandomNumber()
{
    return std::rand();
}
int main()
{
    int n = 10;
    std::vector<int> result;
    generate_n(back_inserter(result), n, generateRandomNumber);
    copy(result.begin(), result.end(), std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
}

测试:https://ideone.com/5xD6P

至于第二个问题,如果我理解正确的话,是如何创建一个带有int参数的函子,忽略它,并调用你的int f()

C ++ 98的方法是实际编写整个仿函数:

struct IgnoreArgument
{
    typedef int(*fp_t)();
    fp_t fp;
    IgnoreArgument(fp_t f) : fp(f) {}
    int operator()(int) const { return fp(); }
};
...
transform(v.begin(), v.end(), v.begin(), IgnoreArgument(f));

测试:https://ideone.com/DTsyl

C ++ 11方法是使用lambda表达式

transform(v.begin(), v.end(), v.begin(), [](int){return f();});

测试:https://ideone.com/nAPXI

C ++ 98 / boost方式是使用boost::bind

transform(v.begin(), v.end(), v.begin(), boost::bind(f));

测试:https://ideone.com/cvd88

答案 1 :(得分:1)

使用generate_n包含您想要的元素数量,以及back_insert_iterator到您希望存储它们的向量,以及指向生成数字的函数的指针。

#include <vector>
#include <algorithm>


int generateRandomNumber()
{
    static int i = 0;
    return 42 + (i++);
}

int main()
{
    std::vector<int> vi;
    std::generate_n(back_inserter(vi), 10, &generateRandomNumber);    
}

请注意,通过像我在这里使用back_insert_iterator一样,您不必预先调整矢量大小,这最好是kludgy。

答案 2 :(得分:1)

这里的问题是transform不适合手头的任务。 transform的意图是采取一些输入,以某种规定的方式对每个输入进行转换,并为每个输入产生输出。

在这种情况下,您不拥有任何输入。如果向量中的值基于某种现有向量中的值(某种方式或其他方式),则transform会有意义。

generate_n确实是问题的正确解决方案 - 它打算调用一些函数/函子N次,产生N个结果,并将它们分配给你提供的输出迭代器(及其后继者)。由于它旨在生成值(而不是转换现有值),函数/仿函数不接受输入,并且您不必提供“假”输入。

就“虚拟”参数而言,想要/需要它可能是一个非常好的迹象(就像在这种情况下)你使用了错误的算法,而且不应该这样做。

但是,您确实会遇到相反的情况:您希望使用提供参数的算法,但您希望能够提供参数。例如,假设您希望能够将数组中的数字设置为随机数,并指定用户指定的某些下限和/或上限。在这种情况下,您希望能够指定将传递给随机数函数的边界,但generategenerate_n都没有这样做的规定。

在这种情况下,您有两种可能性。一个是bind(原boost::bind,但现在包含在C ++ 11中)。我更喜欢使用仿函数,并将参数传递给ctor:

class gen_random { 
    int lower;
    int upper;
public:
    gen_random(int lower = 0, int upper = RAND_MAX) : lower(lower), upper(upper) {}

    int operator() { return rand_range(lower, upper);
};

int main() { 
    std::vector<int> rand_ints;

    std::generate_n(std::back_inserter(rand_ints), 10, gen_random(1, 6));
    return 0;
}