我正在为C ++ 11编写一个JSON类,请参阅http://github.com/nlohmann/json。我的中心数据结构是一个将JSON值类型(null,数组,对象,字符串,bool,数字)包装在一个联合中并通过一个漂亮的C ++接口提供它的类。由于数组(通过std::vector
实现)和对象(std::map
)带有自己的迭代器,我实现了一个"包装器" iterator将对operator++
或operator->
的调用委托给相应的成员变量。此外,我实现了两个附加函数std::string key()
来访问JSON对象的密钥,reference value()
作为operator*()
的别名。
到目前为止,非常好(请参阅https://github.com/nlohmann/json/blob/master/src/json.hpp了解完整的源代码)...
然后我想实施reverse_iterator
和const_reverse_iterator
。这里出现了问题。
using reverse_iterator = std::reverse_iterator<iterator>;
和using const_reverse_iterator = std::reverse_iterator<const_iterator>;
认识到它们,一切都很好,但key()
或{{value()
和reverse_iterator
功能不可用1}}对象。const_reverse_iterator
类reverse_iterator
,我需要再次实现整个班级。仅为class reverse_iterator : public std::reverse_iterator<typename basic_json::iterator>
和key()
提供实现,但对于value()
以及我希望使用operator++()
适配器免费获得的所有其他内容也是不够的我花了很长时间寻找答案,但是我发现所有参考文献要么抓不完整的玩具示例,要么得出结论:迭代器是努力的,人们应该转向Boost ......
所以这是我的问题:
std::reverse_iterator
创建reverse_iterator
,以便它继承尽可能多的功能?iterator
?非常感谢任何帮助!
答案 0 :(得分:0)
不幸的是,我没有得到答案,所以这就是我所做的。也许一个丑陋的解决方案会激起某人发布更好的东西: - )
所以我学到的第一件事是std::reverse_iterator
只是封装了一个&#34; normal&#34;迭代器(称为current
,可通过base()
访问)并建立反向迭代器的关系,即#34;左边的一个元素&#34;而不是&#34;正常&#34;迭代器。
(来自cppreference.com的图片)
只要&#34;正常&#34;迭代器具有标准接口,不使用任何附加功能,即行
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
足以将您自己的迭代器类自动转换为反向迭代器。
使用成员函数
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator crbegin() const { return const_reverse_iterator(cend()); }
const_reverse_iterator crend() const { return const_reverse_iterator(cbegin()); }
可以进行反向迭代,例如像
这样的代码for (my_container::reverse_iterator rit = c.rbegin(); rit != c.rend(); ++it)
{
// rit will iterator container c in reverse order
}
作品。
正如我在问题中写的那样,我将iterator
课程扩展为另外两名成员key()
和value()
。前者允许在迭代期间快速访问JSON对象的键。后者是写it.value()
而不是*it
的别名。不幸的是,上述方法并没有将这些功能继承到reverse_iterator
。
为了丰富用户定义的反向迭代器,我们需要从std::reverse_iterator<iterator>
继承并委托对基本迭代器的调用。不幸的是,我发现除了手动执行此操作之外没有其他方法。对于上述功能,这看起来如下:
class reverse_iterator : public std::reverse_iterator<iterator>
{
...
std::string key() const
{
auto it = --this->base();
return it.key();
}
reference value() const
{
auto it = --this->base();
return it.operator * ();
}
}
最棘手的部分是你需要实现&#34;逐个&#34;手动关系:
base()
检索基础迭代器。有了这个,我们差不多完成了。差不多,因为上面代码中的...
。剩下要做的是将对operator++
等函数的所有其他调用委托给基类。我现在找到了让其他人参加这个无聊代表团的方法。
因此该类包含类似
的代码using base_iterator = std::reverse_iterator<iterator>;
reverse_iterator operator++(int)
{
return base_iterator::operator++(1);
}
reverse_iterator& operator++()
{
base_iterator::operator++();
return *this;
}
(注意base_iterator
的定义。)
那就是它。我们现在有了用户定义的反向迭代器,它允许我们编码
for (my_container::reverse_iterator rit = c.rbegin(); rit != c.rend(); ++it)
{
std::cout << rit.key() << '\n';
}
在关于Github的讨论中,gregmarr建议将reverse_iterator
和const_reverse_iterator
类合并到一个模板类中,如
template<typename Base>
class json_reverse_iterator : public std::reverse_iterator<Base>
{
public:
/// shortcut to the reverse iterator adaptor
using base_iterator = std::reverse_iterator<Base>;
/// the reference type for the pointed-to element
using reference = typename Base::reference;
/// create reverse iterator from iterator
json_reverse_iterator(const typename base_iterator::iterator_type& it)
: base_iterator(it) {}
/// create reverse iterator from base class
json_reverse_iterator(const base_iterator& it) : base_iterator(it) {}
...
}
这允许写
using reverse_iterator = json_reverse_iterator<iterator>;
using const_reverse_iterator = json_reverse_iterator<const_iterator>;
并且快乐。
有关完整代码,请参阅here。
我仍然希望看到避免重复大多数功能的解决方案,但这个对我来说已经足够了。由于我在很长一段时间内没有找到更好的东西,我决定分享它。