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
。
我传入的迭代器是一个基于“flat-file”的自定义 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 requirements include:
Expression
Return type
*a
reference
, convertible to T
这里,a
是一个"value of type X
or const X
",所以MSVC有理由要求const-qualified一元间接运算符; “或”意味着使用迭代器的代码可以使用其中一个,迭代器的作者必须支持两者。 (注意 Cpp17InputIterator 不同于 Cpp17OutputIterator,其中要求的操作是 *r = o
,r
一个 non-const参考,X&
.)
所以你的operator*
应该有const
资格,return有推荐信;具体来说,是对 T
或 const T
的引用(这是 a Cpp17ForwardIterator requirement)。您可以使用 using reference = const T&
并使 cur_
和 cur_valid_
mutable
.
直接满足此要求
这里使用mutable
是完全合法的;因为 operator*() const
是幂等的,所以它是“逻辑常量”,对数据成员的修改是 non-observable.
我得到一个
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
。
我传入的迭代器是一个基于“flat-file”的自定义 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 requirements include:
Expression | Return type |
---|---|
*a |
reference , convertible to T |
这里,a
是一个"value of type X
or const X
",所以MSVC有理由要求const-qualified一元间接运算符; “或”意味着使用迭代器的代码可以使用其中一个,迭代器的作者必须支持两者。 (注意 Cpp17InputIterator 不同于 Cpp17OutputIterator,其中要求的操作是 *r = o
,r
一个 non-const参考,X&
.)
所以你的operator*
应该有const
资格,return有推荐信;具体来说,是对 T
或 const T
的引用(这是 a Cpp17ForwardIterator requirement)。您可以使用 using reference = const T&
并使 cur_
和 cur_valid_
mutable
.
这里使用mutable
是完全合法的;因为 operator*() const
是幂等的,所以它是“逻辑常量”,对数据成员的修改是 non-observable.