【发布时间】:2021-11-17 01:43:20
【问题描述】:
basic_istream_view 是 C++20 中的一个简单的input_range,只有一个begin() 和end() 函数:
template<movable Val, class CharT, class Traits>
requires default_initializable<Val> &&
stream-extractable<Val, CharT, Traits>
class basic_istream_view : public view_interface<
basic_istream_view<Val, CharT, Traits>> {
public:
constexpr iterator begin();
constexpr default_sentinel_t end() const noexcept;
};
它继承了view_interface,在[view.interface]中定义为:
template<class D>
class view_interface {
public:
constexpr bool empty() requires forward_range<D>;
constexpr explicit operator bool()
requires requires { ranges::empty(derived()); };
constexpr auto data() requires contiguous_iterator<iterator_t<D>>;
constexpr auto size() requires forward_range<D>;
constexpr decltype(auto) front() requires forward_range<D>;
constexpr decltype(auto) back() requires bidirectional_range<D>;
template<random_access_range R = D>
constexpr decltype(auto) operator[](range_difference_t<R> n);
};
可以看到view_interface的几乎所有成员函数都要求D是forward_range,而operator bool()要求ranges::empty(derived())是良构的,这也要求D是forward_range .
似乎basic_istream_view 继承view_interface 的唯一目的是为view 建模,因为view 需要view_base 或view_interface 被继承。
但是如果你想让basic_istream_view 成为一个视图,为什么不直接从view_base 继承呢?除了模板实例化的成本之外,我看不到继承 view_interface 的任何好处。
那么,为什么basic_istream_view 继承view_interface 而不是view_base?有历史原因吗?
【问题讨论】:
-
在我看来,它通过 CRTP 为成员函数提供了合适的实现。另请注意 DR LWG 3549:“
view_interface需要从view_base派生,这有时需要在一个视图中包含多个view_base子对象。”。此继承现已从标准中删除 -
"这背后的考虑是什么?" 我不太明白你的问题。这是一个视图。视图应该继承自
view_interface。你还需要什么“注意事项”? -
@Nicol Bolas。我的意思是“为什么 basic_istream_view 继承 view_interface 而不是 view_base?”
-
我的问题是……为什么不应该呢?也就是说,仅仅因为成员函数不可用并不意味着从它继承是不合适的。
-
@NicolBolas。我明白你的意思。在我看来,简单地继承
view_base似乎是一个更好的选择,但这可能只是我的片面之词,谢谢您的不吝赐教。
标签: c++ c++20 std-ranges