"接口(interface)-6ren"> "接口(interface)-我想要实现的目标可能很容易解释:考虑我有一个抽象类,我知道它将包含多个已知类型的对象。然而,保存这些对象的实际容器将在子类中实现。 在我的抽象基类中,我现在想提供一个接口(interface)来迭代这-6ren">
gpt4 book ai didi

C++: "Iterable"接口(interface)

转载 作者:行者123 更新时间:2023-12-04 07:43:15 26 4
gpt4 key购买 nike

我想要实现的目标可能很容易解释:考虑我有一个抽象类,我知道它将包含多个已知类型的对象。然而,保存这些对象的实际容器将在子类中实现。
在我的抽象基类中,我现在想提供一个接口(interface)来迭代这些对象。鉴于我不知道(或者不想修复)容器的类型,我认为迭代器可能是我最好的选择。
此类的概念声明可能如下所示:

class MyClass {
public:
// Other interface methods, e.g. size()

virtual Iterable<MyObject> objects() = 0;
};
这里的目的是我将能够像这样迭代我的类的嵌套对象:
MyClass *class = new ImplementationOfClass();
for (const MyObject &obj : class->objects()) {
// Do stuff with obj
}
然而,我面临的问题是我似乎无法弄清楚 Iterable<MyObject>应该定义。这个对象的关键属性是,在定义这个类时,我只能指定返回值是可迭代的(使用 STL 风格的迭代器),并且会产生类型为 MyObject 的对象。当使用的迭代器被取消引用时。
通常我会为此单独使用一个抽象类,但这似乎非常棘手(不可能?),因为迭代器总是按值传递,因此据我所知,多态是不可能的。
处理如何将任意迭代器类型作为参数传递给函数的问题总是会出现“使用模板”的答案。但是我认为就我而言,我不能为此使用模板。这个假设可能是错误的,所以请随时纠正我。
基本上我总是遇到的障碍是,在某些时候我必须明确地写下迭代器类型,在我的情况下我不能。我考虑过为此使用模板,但这会抑制适当的多态性(我认为?),因为该抽象接口(interface)的用户似乎有明确初始化正确模板的负担。然而,所有这一切的重点是调用者不必关心底层结构。

TL;DR:有没有办法创建一个只 promise 可迭代的接口(interface)类,并且取消引用迭代器会产生一个类型为 T 的对象?

最佳答案

在@FrançoisAndrieux 的帮助和https://stackoverflow.com/a/4247445/3907364 的提示下,我能够想出解决我的问题的方法。
本质上,这个想法是创建一个迭代器包装器,它存储一个函数来获取给定类型的对象(如果给定索引)。然后该索引就是迭代的内容。
这样做的好处是迭代器接口(interface)是通过指定解除引用它应该返回的对象类型来修复的。多态性通过使成员函数objects() 发挥作用。 virtual这样每个子类都可以自己构造迭代器,提供自定义函数指针。因此,只要有办法将索引映射到容器中的相应元素(无论使用哪个),这个技巧都是可用的。
请注意,您可以直接使用指针,例如std::vector<T>::at或创建一个将返回相应元素的自定义函数。
这是迭代器的实现(可能会改进实现,但似乎可以完成工作):

template< typename T > struct iterator_impl {
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = T;
using pointer = T *;
using reference = T &;

using access_function_t = std::function< T &(std::size_t) >;

// regular Ctor
iterator_impl(std::size_t start, access_function_t &func, const void *id)
: m_index(start), m_func(func), m_id(id) {}

// function-move Ctor
iterator_impl(std::size_t start, access_function_t &&func, const void *id)
: m_index(start), m_func(func), m_id(id) {}

// copy Ctor
iterator_impl(const iterator_impl &) = default;

// move ctor
iterator_impl(iterator_impl &&other) {
std::swap(m_index, other.m_index);
m_func = std::move(other.m_func);
std::swap(m_id, other.m_id);
}

// copy-assignment
iterator_impl &operator=(const iterator_impl &other) = default;

// prefix-increment
iterator_impl &operator++() {
++m_index;
return *this;
}

// postfix-increment
iterator_impl operator++(int) {
iterator_impl old = *this;
++(*this);
return old;
}

bool operator==(const iterator_impl &other) { return m_index == other.m_index && m_id == other.m_id; }

bool operator!=(const iterator_impl &other) { return !(*this == other); }

T &operator*() { return m_func(m_index); }

T *operator->() { return &m_func(m_index); };

protected:
std::size_t m_index = 0;
access_function_t m_func;
const void *m_id = nullptr;
};
请注意,我必须介绍 m_id成员变量作为正确比较迭代器的一种手段( std::function 无法使用 == 进行比较)。它的意思是例如包含元素的容器的地址。它的唯一目的是确保恰好具有相同索引但在完全不同的集合上迭代的 2 个迭代器不被视为相等。
基于此,这是 Iterable<T> 的实现。 :
template< typename T > struct Iterable {
using iterator = iterator_impl< T >;
using const_iterator = iterator_impl< const std::remove_const_t< T > >;

Iterable(std::size_t start, std::size_t end, typename iterator_impl< T >::access_function_t &func, const void *id)
: m_begin(start, func, id), m_end(end, func, id) {}

iterator begin() { return m_begin; }
iterator end() { return m_end; }

const_iterator begin() const { return m_begin; }
const_iterator end() const { return m_end; }

const_iterator cbegin() const { return m_begin; }
const_iterator cend() const { return m_end; }

protected:
iterator m_begin;
iterator m_end;
};

关于C++: "Iterable<T>"接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67335987/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com