为啥 string_view 构造函数不采用一对迭代器

Posted

技术标签:

【中文标题】为啥 string_view 构造函数不采用一对迭代器【英文标题】:Why string_view constructor doesn't take a pair of iterators为什么 string_view 构造函数不采用一对迭代器 【发布时间】:2015-11-17 06:36:47 【问题描述】:

boost 中的 string_ref 和 GSL 中的 string_span 都没有定义采用一对迭代器的构造函数。这个决定的原因是什么?

通常这没什么大不了的,我可以像这样创建 string_ref :

boost::string_ref s(start, std::distance(start, finish));

但我希望构造函数采用一对迭代器的原因是因为我的代码如下所示:

template<typename Type, typename Iterator>
void func(const Iterator& begin, const Iterator& end)

    Type s(begin, end);
    //do stuff with s

目前,我可以这样称呼它:

func<std::string>(start, finish)

我想改成:

func<boost::string_ref>(start, finish) //compile error

但该代码无法编译,因为缺少构造函数在 string_ref 中采用一对迭代器

【问题讨论】:

我假设您的迭代器实际上是 std::string::iterator ?因为string_ref 引用了一个现有的字符串,所以你不能凭空构造它。 @MSalters 实际上,我的迭代器已经是boost::string_ref::iterator :)。 在 std 未来提案组中进行了一次值得阅读的讨论:groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/…,值得一读。 【参考方案1】:

boost::string_ref 是对字符串的简单引用,其形式为指向具有预定义长度的连续 内存块的指针。由于迭代器更加通用,因此您不能假设您的 start, finish 范围指的是任何类似连续内存块的东西。

另一方面,std::string 可以从迭代器定义的范围构造,因为它只会复制范围的值,而不管底层数据结构是什么。

【讨论】:

这实际上并不是一个完全令人信服的论点。从std::string::iterator 构造boost::string_ref 是合理的。但即使这样也是不允许的。 @MSalters 没错,至少他们应该能够接受一对boost::string_ref::iterator【参考方案2】:

我创建的辅助函数,希望其他人能发现它有用。简要测试MSVC14/boost 1.59、MSVC17/boost 1.64、MSVC17/C++17

#include <boost/utility/string_ref.hpp>

// todo:  change to std::basic_string_view<charT> in C++17
template <typename charT> using basic_string_view_type = boost::basic_string_ref<charT>;    

// Creates a string view from a pair of iterators
//  http://***.com/q/33750600/882436
template <typename _It>
inline constexpr auto make_string_view( _It begin, _It end )

    using result_type = basic_string_view_type<typename std::iterator_traits<_It>::value_type>;

    return result_type
        ( begin != end ) ? &*begin : nullptr
        ,  (typename result_type::size_type)
        std::max(
            std::distance(begin, end)
            , (typename result_type::difference_type)0
        )
     ;
   // make_string_view

【讨论】:

我刚刚陷入困境:如果 begin == end 并且它们不可取消引用(即它们都指向字符串的末尾),那么 &amp;*begin 会导致 UB。 @Quentin -- 很好,我更新了我的帖子以纠正这个问题,谢谢。现在它只是在 begin==end 时返回一个空字符串视图【参考方案3】:

看来我犯了一个错误。 gsl::string_span 确实有一个带有开始和结束迭代器的构造函数。因此,从迭代器对创建 string_view 没有任何问题,boost::string_ref 中缺少它可能只是一个疏忽。

就我而言,我最终继承自 boost::string_ref 并自己添加构造函数。

【讨论】:

以上是关于为啥 string_view 构造函数不采用一对迭代器的主要内容,如果未能解决你的问题,请参考以下文章

真的没有来自 std::string_view 的 std::string 的显式构造函数吗?

为啥我收到“不包含采用 0 个参数的构造函数”错误? C#

将 std::string 的 xvalue 传递给采用 std::string_view 的函数

C++:调用无参数的构造函数为啥不加括号

为啥 mxml 不支持组件构造函数?

为啥在尝试调用采用动态参数的基本构造函数/方法时会出现此编译错误?