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

How to modify the result of a bound member function for std::generate

本文关键字:generate 绑定 成员 结果 函数 std 何修改 修改      更新时间:2023-10-16

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

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

此外,实际上有一个我知道可以从track*安全地投射到specific_track*。所以我真正想要的是类似于(specific_track*)(*boost::bind(&track_list::next, tracks))的东西,但我不确定如何在语法上构建它。我走在正确的轨道上吗?我查看了提升 lambda,但生成器函数没有参数。

编辑:也许一个更简单的例子可能有助于澄清我想要做什么。

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包装在某种绑定或 lambda 中以执行取消引用,而无需创建单独的函数来执行此操作。

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

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

这似乎与 11 个 lambda C++有关,但我不能使用 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*

}

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

住在科里鲁

#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"));
}

当然,如果你想generate,用generate_n可能会更简单:

住在科里鲁

#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