使用回调初始化向量

时间:2014-02-02 09:57:17

标签: c++ c++11 stl

让我说我有一个班级:

MyType callback(){
 /// randomize here
 .....
 .....
 return randomValue;
}

class MyClass{
private:
  std::vector< MyType > m_vector;

public:
  MyClass( unsigned int size ):m_vector(size, callbackHere? );
};

我需要用我生成的值初始化向量,我该怎么做? 一个解决方案是为MyType创建一个空构造函数,这就是我所拥有的,但现在我想用对替换MyType,因此空构造函数不起作用。

我的回调函数将返回随机值,所以最后我想要一个带有一些随机值的向量。

谢谢

7 个答案:

答案 0 :(得分:5)

您可以编写类似自定义迭代器的类型

  • 在调用前/后缀++时生成新值
  • 通过operator*
  • 取消引用后生成的值
  • 在您完成生成值时等于某个哨兵对象(end迭代器)

答案 1 :(得分:2)

你可以让你的“回调”返回完全生成的向量:

std::vector<std::pair<A, B>> callback(unsigned int size){
  std::vector<std::pair<A, B>> v;
  // Build vector
  return v;
}

然后,您可以使用其移动构造函数初始化m_vector

MyClass(unsigned int size) : m_vector(callback(size)) { }

答案 2 :(得分:1)

您可以使用std::generate_n

std::vector<MyType> v (n);
std::generate_n (v.begin (), n, callback);

变体:

std::vector<MyType> v;
std::generate_n (std::back_inserter (v), n, callback);

如果您在构造函数初始化程序中绝对需要它,请将其置于静态函数中,如Joseph的答案所示。

答案 3 :(得分:1)

您可以构建initializer_list:

#include <iostream>
#include <vector>

typedef std::initializer_list<int> (*callback_function)();
std::initializer_list<int> values() {
    return { 1, 2, 3 };
}

struct X {
    std::vector<int> v;
    X(callback_function f) : v(f()) {};
};

int main() {
    X x(values);
    for(int i: x.v) std::cout << i;
    std::cout << '\n';
}

注意:您将在构造函数中松开大小。

答案 4 :(得分:0)

我对此感到很有趣。以下代码都是C ++ 11。

#include <algorithm>
#include <iostream>
#include <vector>
#include <iterator>
#include <random>

class my_random_generator {
        private:
        static std::random_device rd;
        std::mt19937 gen;
        std::uniform_int_distribution<int> dis;
        public:
        my_random_generator() :
                gen(rd()),
                dis(std::numeric_limits<int>::min(), std::numeric_limits<int>::max())
        {}
        int operator()() {
                return dis(gen);
        }
};

std::random_device my_random_generator::rd;

int main()
{
        std::vector<int> v;
        std::generate_n(std::back_inserter(v), 500, my_random_generator());
        for(auto const &i: v)
                std::cout << i << ',';
        std::cout << std::endl;
        return 0;
}

答案 5 :(得分:0)

编写一个函数来返回已经填充的向量是最简单的解决方案,但是如果你想使用自定义迭代器,这里有一个可能的基本实现

#include <iostream>
#include <vector>
#include <iterator>

template<typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& vec) {
    for (auto& el : vec)
      os << el << ' ';
    return os;
}

template <typename F >
struct GenerateIterator : std::iterator<std::input_iterator_tag, typename std::remove_reference<decltype(std::declval<F>()())>::type> {
    using value_type = typename std::remove_reference<decltype(std::declval<F>()())>::type;

    GenerateIterator() = default;
    GenerateIterator( F &&f, std::size_t num = 0 ) : num_(num), f_(std::forward<F>(f)) {}

    bool operator!=( GenerateIterator const & o ) { return num_ != o.num_; }
    GenerateIterator& operator++(  ) { --num_; return *this; }

    value_type operator*() { return f_(); }
private:
    std::size_t num_{};
    F f_;
};

template <typename F >
GenerateIterator<F>
MakeGenerateIterator( F &&f, std::size_t num = 0 ) {
    return { std::forward<F>(f), num };
}

int bar() {
    static int val{};
    return 2* val++;
}

int main() {
    std::vector<int> foo( MakeGenerateIterator(bar, 10), MakeGenerateIterator(bar) );
    std::cout << foo << std::endl;
}

答案 6 :(得分:0)

我找到了一个解决方案:D非常高兴:

我需要结合boost :: transform_iterator和boost :: counting_iterator

   std::pair<float, float> createInput(unsigned int){
        std::pair<float, float> input(utils::createRandom<float>(1), utils::createRandom<float>(1));
        return input;
    }

Neuron ( unsigned int inputsNumber = 1 ) :  m_neuronWeight( utils::createRandom<Var>(1) ), 
                                            m_output(0), 
                                            m_sum(0),
                                            m_inputs(boost::make_transform_iterator( boost::counting_iterator<unsigned int>(0), createInput ),
                                                     boost::make_transform_iterator( boost::counting_iterator<unsigned int>(inputsNumber), createInput )) {
    if ( inputsNumber == 0 ) {
        throw NNException ( "Wrong argument inputsNumber==0", __FILE__, __LINE__ );
    }
}

希望它对你和我都有用:)