c++ - vector 不满足 Eigen 3.4 中的 std::ranges::contiguous_range

标签 c++ eigen c++20 eigen3 std-ranges

为什么 Eigen::VectorXd不满足概念std::ranges::contiguous_range ?即 static_assert(std::ranges::contiguous_range<Eigen::VectorXd>); 不编译。

此外,是否有可能专门化模板以使 Eigen vector 满足连续范围概念?例如,我们可以专门化 std::ranges::enable_borrowed_range使任何范围满足 std::range::borrowed_range概念。换句话说,有没有办法让上面的静态断言编译通过?

最佳答案

必须选择连续范围。无法仅通过查看迭代器来确定它是连续访问还是只是随机访问。考虑 deque<int>::iterator 之间的区别和 vector<int>::iterator - 它们提供所有相同的操作,返回所有相同的东西,除非vector<int>::iterator,否则你怎么知道?明确告诉你?

Eigen 的迭代器还没有这样做。事实上,在 C++20 之前,并没有开始使用连续迭代器的概念。这是 C++20 范围的新功能。

如果您尝试验证它是否是连续的,您可以看到这一点:

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;
};

关于c++ - vector 不满足 Eigen 3.4 中的 std::ranges::contiguous_range,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70442139/

相关文章:

C++ 协程 : call a coroutine function without co_await

c++ - 我可以在输入迭代器上定义开始和结束吗?

c++ - 如何从这些输出中获取实际的函数名称

c++ - 发布项目 - 当我在 Eclipse 中完成 C++ 项目后该怎么办?

c++ - 从 Eigen::Map 构造 Eigen::Array,它是如何工作的?

c++ - Eigen C++ 包装赋值

C++ std::istream readsome 不读取任何内容

c++ - 我怎么知道 QProcess 什么时候想要读取输入?

c++ - 将 pcl::PointCloud 转换为 Eigen::MatrixBase

c++ - 确保具有 C++20 概念的类方法