C++ 如何为boost::tokenizer实现tokenizer.rbegin()和rend()?
我正在使用boost::tokenizer,但我意识到它不支持rbegin()和rend()。我想问一下如何将这两个函数添加到现有类中 这是来自boost站点:C++ 如何为boost::tokenizer实现tokenizer.rbegin()和rend()?,c++,boost,C++,Boost,我正在使用boost::tokenizer,但我意识到它不支持rbegin()和rend()。我想问一下如何将这两个函数添加到现有类中 这是来自boost站点: #include <iostream> #include <string> #include <boost/tokenizer.hpp> using namespace std; using namespace boost; int main() { string str( "12/12/198
#include <iostream>
#include <string>
#include <boost/tokenizer.hpp>
using namespace std;
using namespace boost;
int main() {
string str( "12/12/1986" );
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
boost::char_separator<char> sep( "/" );
tokenizer tokens( str, sep );
cout << *tokens.begin() << endl;
// cout << *tokens.rbegin() << endl; How could I implement this?
return 0;
}
因为它返回一个iter类型的构造函数(f,first,last),所以我接着转到这个类的源代码。国际热核实验堆实际上是:
typedef typename TGen::type iter;
这是令牌迭代器生成器类。这个类的实现是:
template <
class TokenizerFunc = char_delimiters_separator<char>,
class Iterator = std::string::const_iterator,
class Type = std::string
>
class token_iterator_generator {
private:
public:
typedef token_iterator<TokenizerFunc,Iterator,Type> type;
};
模板<
类TokenizerFunc=char\u分隔符\u分隔符,
类迭代器=std::string::const_迭代器,
类类型=std::string
>
类标记迭代器生成器{
私人:
公众:
typedef令牌\迭代器类型;
};
所以现在我发现Tokenizer类的迭代器实际上是token_迭代器。token_iterator的实现让我非常震惊:
template <class TokenizerFunc, class Iterator, class Type>
class token_iterator
: public iterator_facade<
token_iterator<TokenizerFunc, Iterator, Type>
, Type
, typename detail::minimum_category<
forward_traversal_tag
, typename iterator_traversal<Iterator>::type
>::type
, const Type&
>
{
friend class iterator_core_access;
TokenizerFunc f_;
Iterator begin_;
Iterator end_;
bool valid_;
Type tok_;
void increment(){
BOOST_ASSERT(valid_);
valid_ = f_(begin_,end_,tok_);
}
const Type& dereference() const {
BOOST_ASSERT(valid_);
return tok_;
}
template<class Other>
bool equal(const Other& a) const{
return (a.valid_ && valid_)
?( (a.begin_==begin_) && (a.end_ == end_) )
:(a.valid_==valid_);
}
void initialize(){
if(valid_) return;
f_.reset();
valid_ = (begin_ != end_)?
f_(begin_,end_,tok_):false;
}
public:
token_iterator():begin_(),end_(),valid_(false),tok_() { }
token_iterator(TokenizerFunc f, Iterator begin, Iterator e = Iterator())
: f_(f),begin_(begin),end_(e),valid_(false),tok_(){ initialize(); }
token_iterator(Iterator begin, Iterator e = Iterator())
: f_(),begin_(begin),end_(e),valid_(false),tok_() {initialize();}
template<class OtherIter>
token_iterator(
token_iterator<TokenizerFunc, OtherIter,Type> const& t
, typename enable_if_convertible<OtherIter, Iterator>::type* = 0)
: f_(t.tokenizer_function()),begin_(t.base())
,end_(t.end()),valid_(!t.at_end()),tok_(t.current_token()) {}
Iterator base()const{return begin_;}
Iterator end()const{return end_;};
TokenizerFunc tokenizer_function()const{return f_;}
Type current_token()const{return tok_;}
bool at_end()const{return !valid_;}
};
模板
类标记迭代器
:公共迭代器<
令牌迭代器
,类型
,typename详细信息::最小类别<
前向遍历标记
,typename迭代器\遍历::类型
>::类型
,常量类型&
>
{
友元类迭代器\u核心\u访问;
TokenizerFunc f_2;;
迭代器begin;
迭代器结束;
布尔有效值;
tok_型;
无效增量(){
BOOST_断言(有效);
有效=f(开始、结束、结束);
}
常量类型&取消引用()常量{
BOOST_断言(有效);
返回tok_;
}
模板
布尔相等(常数其他和a)常数{
返回(a.valid&&valid)
((a.begin.==begin.&&(a.end.==end.)
:(a.valid=有效的);
}
void initialize(){
如果(有效)返回;
f_.reset();
有效的\=(开始\!=结束\)?
f(开始、结束、结束):false;
}
公众:
标记迭代器():开始(),结束(),有效(假),tok_u(){}
token_迭代器(TokenizerFunc f,迭代器begin,迭代器e=iterator())
:f_uf(f),begin_u(begin),end_u(e),valid_u(false),tok_uu(){initialize();}
令牌\迭代器(迭代器开始,迭代器e=iterator())
:f_(),begin_(begin),end_(e),valid_(false),tok_(){initialize();}
模板
令牌迭代器(
令牌迭代器常量&t
,typename启用(如果可转换::type*=0)
:f_u(t.tokenizer_function()),begin_u(t.base())
,end_(t.end()),valid_(!t.at_end()),tok_(t.current_token()){}
迭代器base()常量{return begin;}
迭代器end()常量{return end;};
TokenizerFunc标记器函数()常量{return f_;}
键入current_token()const{return tok_;}
bool at_end()常量{return!valid_;}
};
这个类非常复杂,我在这里迷路了:(!iterator_facade的继承部分非常复杂。
我下一步该走了吗
谢谢,考虑到这一点(来自)
tokenizer类提供序列中包含的一系列令牌的容器视图。您可以在构造时或使用assign member函数设置要解析的序列和要用于解析序列的tokenizer函数。注意:构造时实际上不进行解析。解析是在访问令牌时按需完成的通过begin提供的迭代器
我想说你几乎可以复制粘贴代码,但是从str[strlen(str)-1]开始直到0。但是,您首先必须创建一个名为reverse_iterator的typedef,并在反向迭代器到达字符串开头时按需解析令牌。在进行此操作时,请毫不犹豫地显示您的进度并提出问题。您当然可以通过简单地迭代stri来创建一个实现此功能的新类使用普通标记器进行标记并将值存储在向量中。然后使用向量实现rend和rbegin 简单且几乎没有出错的风险,尽管在运行时可能不是最快的,也不是最不占用内存的。除非您知道这将是一个问题,否则这是我将采取的路线,因为它非常容易实现,速度也很快 但是,您特别要求扩展现有的类,我认为这是一个坏主意。在这种情况下,最简单的方法可能是使用rbegin()和rend()而不是begin()和end()来更改接受容器(您正在使用的容器)的构造函数来实例化内部标记器对象用于容器。要实现自己的rbegin()和rend()从内部标记器的开始和结束处获得的迭代器开始。但是,从这些标记器返回的标记可能是向后的,因此需要反转这些标记。但是,使用boost::iterators包很容易实现实际的迭代器类型 请注意,您需要特别注意使用显式迭代器的构造函数,或者决定只为反向迭代器实现类功能的一个子集(在这种情况下,您可能应该使用一个单独的类来保留两个内部标记化器,而不是假装成boost::标记化器) 另一种方法是更改char_分隔符(和其他分隔符类),以便可以显式指定标记器_detail::assign_或_plus_equal的专门化,以便可以将每个char添加到每个部分字符串的开头而不是结尾 希望这能有所帮助。我会选择第一种选择,或者只是简单地更改我的需求,这样我就不需要反向迭代器了。我建议使用
#包括
标准:字符串str(“12/12/1986”);
std::矢量结果;
boost::algorithm::split(results,str,boost::algorithm::is_any_of(“/”);
(见附件)
因此,您可以使用rbegin()和rend()轻松迭代生成的std::vector
template <
class TokenizerFunc = char_delimiters_separator<char>,
class Iterator = std::string::const_iterator,
class Type = std::string
>
class token_iterator_generator {
private:
public:
typedef token_iterator<TokenizerFunc,Iterator,Type> type;
};
template <class TokenizerFunc, class Iterator, class Type>
class token_iterator
: public iterator_facade<
token_iterator<TokenizerFunc, Iterator, Type>
, Type
, typename detail::minimum_category<
forward_traversal_tag
, typename iterator_traversal<Iterator>::type
>::type
, const Type&
>
{
friend class iterator_core_access;
TokenizerFunc f_;
Iterator begin_;
Iterator end_;
bool valid_;
Type tok_;
void increment(){
BOOST_ASSERT(valid_);
valid_ = f_(begin_,end_,tok_);
}
const Type& dereference() const {
BOOST_ASSERT(valid_);
return tok_;
}
template<class Other>
bool equal(const Other& a) const{
return (a.valid_ && valid_)
?( (a.begin_==begin_) && (a.end_ == end_) )
:(a.valid_==valid_);
}
void initialize(){
if(valid_) return;
f_.reset();
valid_ = (begin_ != end_)?
f_(begin_,end_,tok_):false;
}
public:
token_iterator():begin_(),end_(),valid_(false),tok_() { }
token_iterator(TokenizerFunc f, Iterator begin, Iterator e = Iterator())
: f_(f),begin_(begin),end_(e),valid_(false),tok_(){ initialize(); }
token_iterator(Iterator begin, Iterator e = Iterator())
: f_(),begin_(begin),end_(e),valid_(false),tok_() {initialize();}
template<class OtherIter>
token_iterator(
token_iterator<TokenizerFunc, OtherIter,Type> const& t
, typename enable_if_convertible<OtherIter, Iterator>::type* = 0)
: f_(t.tokenizer_function()),begin_(t.base())
,end_(t.end()),valid_(!t.at_end()),tok_(t.current_token()) {}
Iterator base()const{return begin_;}
Iterator end()const{return end_;};
TokenizerFunc tokenizer_function()const{return f_;}
Type current_token()const{return tok_;}
bool at_end()const{return !valid_;}
};
#include <boost/algorithm/string/split.hpp>
std::string str("12/12/1986");
std::vector<std::string> results;
boost::algorithm::split(results, str, boost::algorithm::is_any_of("/"));