如何修改std :: generate的绑定成员函数的结果

时间:2017-06-09 05:19:54

标签: c++ boost stl

我正在使用与Boost 1.60(无C ++ 11)兼容的VS2008代码。我有一个第三方库,它返回一个类似列表的界面。我想获取列表的元素并将它们放在std :: vector中。 track_list类有一个next方法,它返回一个指向轨道指针track**的指针。

我在想我可以使用std :: generate来填充与track_list相同大小的向量。我能够提出boost::bind(&track_list::next, tracks)来获取track**,但我不确定如何添加解除引用部分以使track*进入vector<track*>

此外,实际上我知道从specific_track*投出的track*是安全的。所以我真正想要的是(specific_track*)(*boost::bind(&track_list::next, tracks))的内容,但我不确定如何在语法上构造它。我是在正确的轨道上吗?我看了一下boost lambdas,但是生成器函数没有参数。

编辑:也许更简单的例子可能有助于澄清我正在尝试做的事情。

int** get_ptr_num() { int* i = new int(5); return new int*(i); }
int* get_num() { return new int(5); }

int main() {
  std::vector<int*> nums(10);
  std::generate(nums.begin(), nums.end(), get_num) // compiles      
  std::generate(nums.begin(), nums.end(), get_ptr_num) // cannot convert from int** to int*
}

基本上我只想将get_ptr_num包装在某种bind或lambda中来进行解引用而不创建单独的函数来执行此操作。

第二部分,演员,会是这样的:

int main() {
  std::vector<double*> nums(10);    
  std::generate(nums.begin(), nums.end(), get_ptr_num) // cannot convert from int** to double*
}

这似乎对C ++ 11 lambdas来说是微不足道的,但我不能使用C ++ 11。

关于这个成员函数的最后一部分将更像是这样:

class IntGenerator {
public:
  int** get_ptr_num() { int* i = new int(5); return new int*(i); }
}

int main() {
  IntGenerator int_gen;
  std::vector<int*> nums(10);
  std::generate(nums.begin(), nums.end(), boost::bind(&IntGenerator::get_ptr_num, int_gen)) // cannot convert from int** to int*

}

1 个答案:

答案 0 :(得分:0)

您可以使用函数输入迭代器:

<强> Live On Coliru

#include <boost/iterator/function_input_iterator.hpp>
#include <vector>
#include <functional>
#include <iostream>
#include <array>

namespace TheAPI {

    struct track_list {
        std::array<char const*, 6> titles {{ "one", "two", "three", "four", "five", "six" }};
        size_t length() const { return titles.size(); }

        struct Iterator {
            char const* const* raw;
            char const* next() { return *raw++; }
        };

        Iterator get_iterator() const { return {titles.begin()}; };
    };

}

int main() {
    TheAPI::track_list tl;
    auto iter = tl.get_iterator();

    auto gen = std::bind(&TheAPI::track_list::Iterator::next, std::ref(iter));

    auto first = boost::make_function_input_iterator(gen, 0),
         last  = boost::make_function_input_iterator(gen, 6);

    std::vector<std::string> titles(first, last);

    std::copy(titles.begin(), titles.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
}

当然,如果您考虑generategenerate_n可能会更简单:

<强> Live On Coliru

#include <functional>
#include <iterator>
#include <algorithm>
#include <iostream>
#include <array>

namespace TheAPI {

    struct track_list {
        std::array<char const*, 6> titles {{ "one", "two", "three", "four", "five", "six" }};
        size_t length() const { return titles.size(); }

        struct Iterator {
            char const* const* raw;
            char const* next() { return *raw++; }
        };

        Iterator get_iterator() const { return {titles.begin()}; };
    };

}

int main() {
    TheAPI::track_list tl;
    auto iter = tl.get_iterator();

    auto gen = std::bind(&TheAPI::track_list::Iterator::next, std::ref(iter));
    std::generate_n(std::ostream_iterator<std::string>{std::cout, "\n"}, tl.length(), gen);
}

使用

填充矢量
std::vector<std::string> my_vector;
std::generate_n(back_inserter(my_vector), tl.length(), gen);

两个程序都打印

one
two
three
four
five
six