簡體   English   中英

向量在 Eigen 3.4 中不滿足 std::ranges::contiguous_range

[英]Vectors do not satisfy std::ranges::contiguous_range in Eigen 3.4

為什么Eigen::VectorXd不滿足概念std::ranges::contiguous_range static_assert(std::ranges::contiguous_range<Eigen::VectorXd>); 不編譯。

此外,是否有可能專門化模板以使特征向量滿足連續范圍概念? 例如,我們可以std::ranges::enable_borrowed_range以使任何范圍滿足std::range::borrowed_range ::range::borrowed_range 概念。 換句話說,有沒有辦法讓上面的 static 斷言編譯?

必須選擇連續范圍。 無法僅通過查看迭代器來確定它是連續訪問還是隨機訪問。 考慮一下deque<int>::iteratorvector<int>::iterator之間的區別——它們提供所有相同的操作,返回所有相同的東西,除非vector<int>::iterator明確告訴你,否則你怎么知道?

Eigen 的迭代器還沒有這樣做。 事實上,在 C++20 之前,並沒有連續迭代器的概念。 這是 C++20 Ranges 的新功能。

如果您嘗試驗證它是連續的,您可以看到這一點:

using I = Eigen::VectorXd::iterator;
static_assert(std::contiguous_iterator<I>);

在 gcc 上,診斷指示:

/opt/compiler-explorer/gcc-trunk-20211221/include/c++/12.0.0/concepts:67:13:   required for the satisfaction of 'derived_from<typename std::__detail::__iter_concept_impl<_Iter>::type, std::contiguous_iterator_tag>' [with _Iter = Eigen::internal::pointer_based_stl_iterator<Eigen::Matrix<double, -1, 1, 0, -1, 1> >]
/opt/compiler-explorer/gcc-trunk-20211221/include/c++/12.0.0/concepts:67:28: note:   'std::contiguous_iterator_tag' is not a base of 'std::random_access_iterator_tag'
   67 |     concept derived_from = __is_base_of(_Base, _Derived)
      |                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

基本上,我們的類別是隨機訪問,而不是連續的。

Eigen 正確執行此操作的方法是添加:

 template<typename XprType>
 class pointer_based_stl_iterator
 {
   enum { is_lvalue  = internal::is_lvalue<XprType>::value };
   typedef pointer_based_stl_iterator<typename internal::remove_const<XprType>::type> non_const_iterator;
   typedef pointer_based_stl_iterator<typename internal::add_const<XprType>::type> const_iterator;
   typedef typename internal::conditional<internal::is_const<XprType>::value,non_const_iterator,const_iterator>::type other_iterator;
   // NOTE: in C++03 we cannot declare friend classes through typedefs because we need to write friend class:
   friend class pointer_based_stl_iterator<typename internal::add_const<XprType>::type>;
   friend class pointer_based_stl_iterator<typename internal::remove_const<XprType>::type>;
 public:
   typedef Index difference_type;
   typedef typename XprType::Scalar value_type;
   typedef std::random_access_iterator_tag iterator_category;
+  typedef std::contiguous_iterator_tag iterator_concept;
   typedef typename internal::conditional<bool(is_lvalue), value_type*, const value_type*>::type pointer;
   typedef typename internal::conditional<bool(is_lvalue), value_type&, const value_type&>::type reference;
};

這將使其成為 C++20 連續迭代器。

或者,您可以自己在外部執行此操作,盡管這不是一個好主意(實際上,應該正確執行此操作的是 Eigen),並且必須在任何范圍使用之前完成:

template <>
struct std::iterator_traits<I> {
    using iterator_concept = std::contiguous_iterator_tag;
    using iterator_category = std::random_access_iterator_tag;
    using value_type = typename I::value_type;
    using difference_type = typename I::difference_type;
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM