繁体   English   中英

msvc std::lower_bound 需要 const 运算符*

[英]msvc std::lower_bound requires const operator*

我得到一个

Error   C2678   binary '*': no operator found which takes a left-hand operand of type 'const _InIt' (or there is no acceptable conversion)

它由 MSVC (2022, V17.1) <algorithm> header 中的这段代码抛出。

template <class _FwdIt, class _Ty, class _Pr>
_NODISCARD _CONSTEXPR20 _FwdIt lower_bound(_FwdIt _First, const _FwdIt _Last, const _Ty& _Val, _Pr _Pred) {

...
        const auto _UMid                   = _STD next(_UFirst, _Count2);
        if (_Pred(*_UMid, _Val)) { // try top half

第二行由于上面一行的const而抛出错误。

我传入的迭代器是一个基于“平面文件”的自定义 LegacyRandomAccessIterator,它的operator*如下所示:

  value_type operator*() { return current(); }

...

  ValueType current() {
    if (!cur_valid_) {
      cur_       = ffdb_->get_record(pos_);
      cur_valid_ = true;
    }
    return cur_;
  }

换句话说,我不能只将我的operator*标记为const ,因为它不是,也不可能是——它正在从磁盘加载一组缓冲记录,而这不是当前设计中的const操作。

我实现了一个“虚拟” const版本来证明这是问题所在:

 value_type operator*() const { return value_type{}; }

错误消失了,但显然这没有做任何事情。

libstdc++ 没有对const operator*的这种期望。 (我还没有测试过 libc++)

如果不对我的迭代器进行一些重大的重新设计,这是可以解决的吗?

MSVC的实现有这个期望合理吗?

std::lower_bound采用Cpp17ForwardIterator ,它也必须是Cpp17InputIterator Cpp17InputIterator 要求包括

表达 返回类型
*a reference ,可转换为T

在这里, a“类型Xconst X的值” ,因此 MSVC 有理由要求 const 限定的一元间接运算符; “或”意味着使用迭代器的代码可以使用其中一个,迭代器的作者必须支持两者。 (请注意, Cpp17InputIterator不同于Cpp17OutputIterator ,其中所需的操作是*r = o ,其中r是非常量引用X& 。)

所以你的operator*应该有const资格,并返回一个引用; 具体来说,是对Tconst T的引用(这是Cpp17ForwardIterator的要求)。 您可以通过using reference = const T&并使cur_cur_valid_ mutable来直接满足这一点。

在这里使用mutable是完全合法的; 由于operator*() const是幂等的,因此它是“逻辑上的 const”,并且对数据成员的修改是不可观察的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM