将make_iterator_range与std :: string一起使用

时间:2015-06-28 16:12:16

标签: c++ boost iterator

我想对子字符串进行to_upper()调用,从而传入一个范围。我不明白为什么我无法在string上构建范围,但可以vector以同样的方式构建范围。

将Xcode 6.3.2与编译器选项-std=c++11和Boost 1.58

一起使用
void string_test() {
    std::string my_str = "Hello, world, it's a wonderful day";    
    std::vector<int> x  = {1,2,3,4,5,6,6,8,9,10};
    const auto rng = boost::make_iterator_range(x.begin(),x.end()-5);
    const auto rng2 = boost::make_iterator_range(my_str.begin(),my_str.begin()+10);
    // How do I get to_upper_copy to accept the range returned above
    std::cout << boost::to_upper_copy(rng2) << std::endl;

}

我在Xcode中收到错误:

/usr/local/Cellar/boost/1.58.0/include/boost/range/iterator_range_core.hpp:215:11: No matching constructor for initialization of 'std::__1::__wrap_iter<char *>'

2 个答案:

答案 0 :(得分:2)

该错误与从iterator_range创建string没有任何关系;如果您注释掉对to_upper_copy的调用,您的代码将被编译。同样,如果您将stringvector<char>(或甚至vector<int>)交换,则对to_upper_copy的调用将再次无法编译并出现类似错误。

显然,罪魁祸首是to_upper_copy,查看功能模板的签名会告诉我们原因。

template<typename SequenceT> 
SequenceT to_upper_copy(const SequenceT &, 
                        const std::locale & = std::locale());

您无法传递一对string::iterator s,这是make_iterator_range调用基本上返回的SequenceT,因为算法无法轻松构建新的SequenceT RangeT给出了一对迭代器。这也在Boost documentation中描述:

  

此外,一些算法对字符串类型有额外的要求。特别地,要求算法可以创建给定类型的新字符串。在这种情况下,要求类型满足序列(Std§23.1.1)要求。

     

在引用和代码中,字符串类型的要求由template参数的名称指定。 SequenceT表示基本范围要求必须保持。 iterator_range表示扩展序列要求

请注意,上面提到的部分来自C ++ 03标准。在C ++ 11及更高版本的文档中,相关部分是§23.2.3[sequence.reqmts]

因此SequenceT不符合my_str的要求。如果您将to_upper_copy传递给string,则代码会进行编译。但是,如果您只想转换子字符串,则需要创建一个包含该字符串的to_upper,然后调用std::cout << boost::to_upper_copy(my_str) << std::endl; // works, but not a sub-string std::string substr(rng2.begin(), rng2.end()); boost::to_upper(substr); std::cout << substr << std::endl;

to_upper_copy

您还可以通过使用带有输出迭代器参数的std::string result; result.reserve(rng2.size()); boost::to_upper_copy(std::back_inserter(result), rng2); std::cout << result << std::endl; 重载来避免构造中间子字符串。

DateTimeKind=Utc

Live demo

答案 1 :(得分:0)

在@ Praetorian的回答之后我终于意识到你可以通过使用在输出迭代器中传递的重载的to_upper_copy()来完全删除较小的字符串分配或向量副本。

public bool? WillAttend { get; set; }