我正在实现自定义分页器。
例如。
vector<int> v{1,2,3,4};
for (auto page : Paginator(begin(v), end(v), 2)) {
// For the first iteration i expect {1, 2}, and for the second {3, 4}
}
我的代码有错误:
/home/alex/dev/main.cpp:32:28: error: could not convert ‘((Paginator<__gnu_cxx::__normal_iterator<int*, std::vector<int> > >*)this)->Paginator<__gnu_cxx::__normal_iterator<int*, std::vector<int> > >::data_.std::vector<_Tp, _Alloc>::begin<std::vector<__gnu_cxx::__normal_iterator<int*, std::vector<int> >, std::allocator<__gnu_cxx::__normal_iterator<int*, std::vector<int> > > >, std::allocator<std::vector<__gnu_cxx::__normal_iterator<int*, std::vector<int> >, std::allocator<__gnu_cxx::__normal_iterator<int*, std::vector<int> > > > > >()’ from ‘std::vector<std::vector<__gnu_cxx::__normal_iterator<int*, std::vector<int> >, std::allocator<__gnu_cxx::__normal_iterator<int*, std::vector<int> > > >, std::allocator<std::vector<__gnu_cxx::__normal_iterator<int*, std::vector<int> >, std::allocator<__gnu_cxx::__normal_iterator<int*, std::vector<int> > > > > >::iterator {aka __gnu_cxx::__normal_iterator<std::vector<__gnu_cxx::__normal_iterator<int*, std::vector<int> >, std::allocator<__gnu_cxx::__normal_iterator<int*, std::vector<int> > > >*, std::vector<std::vector<__gnu_cxx::__normal_iterator<int*, std::vector<int> >, std::allocator<__gnu_cxx::__normal_iterator<int*, std::vector<int> > > >, std::allocator<std::vector<__gnu_cxx::__normal_iterator<int*, std::vector<int> >, std::allocator<__gnu_cxx::__normal_iterator<int*, std::vector<int> > > > > > >}’ to ‘__gnu_cxx::__normal_iterator<int*, std::vector<int> >’
return data_.begin();
我的代码
template<class IterT>
class Paginator {
public:
Paginator(IterT begin, IterT end, size_t sz) {
pageSize_ = sz;
const size_t dist = distance(begin, end);
parts_ = dist / pageSize_;
if (dist % pageSize_ != 0) {
++parts_;
}
for (int i = 1; i <= parts_; ++i) {
IterT start = next(begin, (i - 1) * pageSize_);
IterT finish = next(begin, i * pageSize_);
data_.push_back({start, finish});
}
}
size_t size() const {
return parts_;
}
IterT begin() {
return data_.begin();
}
IterT end() {
return data_.end();
}
private:
size_t pageSize_;
size_t parts_;
vector<vector<IterT>> data_;
};
template<class T>
void Print(const vector<T>& v) {
for (auto i : v) {
cout << i << ' ';
}
cout << endl;
}
int main() {
vector<int> v{1,2,3,4,5,6,7,8,9};
for (auto i : Paginator<vector<int>::iterator>(begin(v), end(v), 2)) {
Print(i);
}
}
最佳答案
IterT begin() {
return data_.begin();
}
IterT end() {
return data_.end();
}
vector<vector<IterT>> data_;
data_.begin()
的类型不是IterT
,而是std::vector<std::vector<IterT>>::iterator
。这些类型不会转换。
简单的解决方法是使
begin()
和end()
返回auto
。您的
data_
是迭代器 vector 的 vector 。vector<int> v{1,2,3,4};
for (auto page : Paginator(begin(v), end(v), 2)) {
// For the first iteration i expect {1, 2}, and for the second {3, 4}
}
在这里,
page
“应该”是std::vector<std::vector<int>::iterator>
。如果您希望将其作为std::vector<int>
,则需要重新设计。 for (int i = 1; i <= parts_; ++i) {
IterT start = next(begin, (i - 1) * pageSize_);
IterT finish = next(begin, i * pageSize_);
data_.push_back({start, finish});
}
该代码具有边界检查问题。对于非随机访问迭代器,它的效率也不高。
它生成一个正好包含2个元素的
vector<IterT>
,一个是范围的开始,一个是结束。我怀疑这不是您想要的。您想要的是
vector< std::iterator_traits<IterT>::value_type >
。template<class IterT>
class Paginator {
public:
using value_type = typename std::iterator_traits<IterT>::value_type;
Paginator(IterT begin, IterT end, std::size_t sz):
pageSize_(sz)
{
const std::size_t dist = std::distance(begin, end);
parts_ = (dist+pageSize_-1) / pageSize_;
for (std::size_t i = 0; i < parts_; ++i) {
IterT start = std::next(begin, i * pageSize_);
IterT finish = std::next(begin, (std::min)( (i+1) * pageSize_, dist ));
data_.emplace_back(start, finish);
}
}
std::size_t size() const {
return parts_;
}
auto begin() const {
return data_.begin();
}
auto end() const {
return data_.end();
}
private:
std::size_t pageSize_ = 0;
std::size_t parts_ = 0;
std::vector<std::vector<value_type>> data_;
};
Live example。
如果要避免复制内容,可以编写一个
range_t
类,该类公开begin
和end
并存储两个迭代器。这将使相同的测试代码有效,而无需在Paginator
结构中复制数据。OP包含一些明显的c++17代码,但问题要求输入c++11。
要使以上工作在c++11中,请添加:
using value_type = typename std::iterator_traits<IterT>::value_type;
using storage = std::vector<std::vector<value_type>>;
using iterator = typename storage::iterator;
然后
iterator begin() const {
和
iterator end() const {
关于c++ - 无法转换类型C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60084094/