程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了如何创建一个调用成员函数的类似 stl 的迭代器大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决如何创建一个调用成员函数的类似 stl 的迭代器?

开发过程中遇到如何创建一个调用成员函数的类似 stl 的迭代器的问题如何解决?下面主要结合日常开发的经验,给出你关于如何创建一个调用成员函数的类似 stl 的迭代器的解决方法建议,希望对你解决如何创建一个调用成员函数的类似 stl 的迭代器有所启发或帮助;

我想为我的 API 提供一些迭代器,这些迭代器会自动调用所需的成员函数来直接迭代返回的值。更准确地将以下结构体和主函数视为 MVE:


struct Shape
{
  double getArea()
  {
  return ....//calculate area;
  }

  double getVolume()
  {
  return ....//calculate volume;
  }

  std:pair<double,double> getVolumeAndArea()
  {
  return std:make_pair...;
  }

// some data members
}

现在我有一个形状向量,我想按以下方式使用它:


int main(){

std:vector<Shape> shapes;
//fill shapes

for(const auto area : area(shapes))
  // do something with area


for(const auto volume : volume(shapes))
  // do something with volume


for(const auto [volume,area] : volumeAndArea(shapes))
  // do something with volume and area
}

显然,我可以迭代形状并直接在代码中编写它,或者在提供的 Lamba 内部调用发生的地方编写一些 std:for_each

尽管如此,我认为我想到的方法对于潜在用户来说不那么冗长。

因此,我的问题是如何用最少的样板来解决这个问题。@R_788_10675@用一些 boost 迭代器还是继承一些 std::iterator 作为这些免费函数的返回值?我希望有一种我已经监督过的简单方法。由于提到的选项似乎很冗长。拥有这个相当通用的东西也会很好。因为在不重复迭代器样板的情况下将它用于多个类会很好。

此外,我不限于旧的 c++ 版本,因此,也欢迎使用不错的 c++20 解决方案。

因此,有人可以向我指出如何以现代方式执行此操作的好示例或最佳实践建议吗?我有信心自己锻炼细节,因为我不想要求完成的解决方案。

解决方法

在 C++20 中,算法的范围版本可以对成员进行投影,这几乎可以让您获得所需的易用性,但语法略有不同

std::ranges::for_each(shapes,[](const auto & area) {
    // do something with area
},&Shape::getArea);
// ^_____________^ projection on member

这是一个demo

,

这是一个可能的实现,它使用迭代器而不是任何范围(特别是对于区域情况):

class area {
private:
    class iterator {
    public:
        // needed so that it acts like a std::iterator
        using difference_type = int;
        using value_type = double;
        using reference = double;
        using pointer = std::add_pointer<value_type>;
        using iterator_category = std::forWARD_iterator_tag;

        double operator*() const {
            // compute the area when accessing the value of the iterator
            return shapes_[index_].getArea();
        }

        iterator &operator++() {
            index_++;
            return *this;
        }

        bool operator==(const iterator &rhs) const { return index_ == rhs.index_; }
        bool operator!=(const iterator &rhs) const { return !(*this == rhs); }
        bool operator<(const iterator &rhs) const { return index_ < rhs.index_; }

        iterator(size_t index,const std::vector<Shape>& shapes) : index_(indeX),shapes_(shapes) {}

    private:
        size_t index_;
        const std::vector<Shape>& shapes_;
    };

public:
    area(const std::vector<Shape>& shapes) : shapes_(shapes) {}
    iterator begin() const { return iterator{0,shapes_}; }
    iterator end() const{ return iterator{shapes_.size(),shapes_}; }

private:
    const std::vector<Shape>& shapes_;
};

...

int main() {
    std::vector<Shape> shapes;
    for (const double area : area(shapes)) {

    }
}

范围看起来容易多了!

就其价值而言,您可能可以在此处提取 iterator 类并将其重用于所有不同的函数(例如传递一个 std::function 对每个形状调用)。

,

我想我是通过上面给出的有用提示弄明白的。谢谢 cigien、mattlangford 和 mooning duck。

使用 std::ranges::transform_view 和投影为编写以下内容提供了很好且富有表现力的选择

using std::ranges::transform_view;
for(const auto area : transform_view(shapes,&Shape::getArea ))
        std::cout << area << "\n";

另见https://godbolt.org/z/3xQn5bdWE。

还提供一种类似 API 的解决方案,可以将其包装为:

auto area(std::vector<Shape>& shapes)
{
    using std::ranges::transform_view;
    return transform_view(shapes,&Shape::getArea);
}

然后可以用作

for(const auto area :  area(shapes))
   //do something with area

由于原始的 transform_view 版本也非常具有表现力,我认为 area(...) 解决方案更难理解。

https://godbolt.org/z/Gff8K9cr8。

大佬总结

以上是大佬教程为你收集整理的如何创建一个调用成员函数的类似 stl 的迭代器全部内容,希望文章能够帮你解决如何创建一个调用成员函数的类似 stl 的迭代器所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。