我有一组大小相同的 vector ,我想为用户提供一个接口(interface),以获取这些 vector 子集的迭代器范围。
以下示例显示了 getRange
中有问题的行:它的想法是接收一堆类型(指定 vector 的类型)和同样多的索引(指定 vector 的位置)。代码可以编译,但问题是 i++
永远不会按预期执行,即调用总是只有 i
(等于 0)。如果用户试图获取不同的类型,这也会通过 boost::get
导致运行时错误。
这可能是一个众所周知的问题。有什么巧妙的解决方案?
#include <vector>
#include <boost/variant.hpp>
#include <boost/range/combine.hpp>
template <typename... T>
struct VectorHolder
{
template<typename X>
using Iterator = typename std::vector<X>::const_iterator;
std::vector<boost::variant<std::vector<T>...> > vecs_;
template <typename X>
auto begin(int idx) const {
return boost::get<std::vector<X> >(vecs_.at(idx)).cbegin();
}
template <typename X>
auto end(int idx) const {
return boost::get<std::vector<X> >(vecs_.at(idx)).cend();
}
};
template <typename... T, typename VectorHolder>
auto getRange(const VectorHolder& vh, const std::vector<int>& idx)
{
assert(sizeof...(T) == idx.size());
// Fetch a boost::iterator_range over the specified indices
std::size_t i = 0;
std::size_t j = 0;
// PROBLEM: i and j not incremented as intended
return boost::combine(
boost::iterator_range<VectorHolder::Iterator<T>>(
vh.begin<T>(idx[i++]), vh.end<T>(idx[j++]))...);
}
int main()
{
VectorHolder<bool, int, double> vh;
vh.vecs_.push_back(std::vector<int>(5, 5));
vh.vecs_.push_back(std::vector<bool>(5));
vh.vecs_.push_back(std::vector<double>(5, 2.2));
vh.vecs_.push_back(std::vector<int>(5, 1));
const std::vector<int> idx = { 0, 3 };
for (auto t : getRange<int, int>(vh, idx))
{
std::cout << t.get<0>() << " " << t.get<1>() << "\n";
}
}
最佳答案
std::index_sequence
帮助:
template <typename... Ts, typename VectorHolder, std::size_t ... Is>
auto getRange(const VectorHolder& vh, const std::vector<int>& idx, std::index_sequence<Is...>)
{
assert(sizeof...(Ts) == idx.size());
return boost::combine(
boost::iterator_range<typename VectorHolder::template Iterator<Ts>>(
vh.template begin<Ts>(idx[Is]), vh.template end<Ts>(idx[Is]))...);
}
template <typename... Ts, typename VectorHolder>
auto getRange(const VectorHolder& vh, const std::vector<int>& idx)
{
return getRange<Ts...>(vh, idx, std::index_sequence_for<Ts...>());
}
关于c++ - 使用可变参数模板和运行时索引构建 iterator_range,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57292333/