我的构造函数有问题。
我收到以下错误:
未知参数1从“
std::_Rb_tree_const_iterator<std::__cxx11::basic_string<char> >*
”到“std::multiset<std::__cxx11::basic_string<char> >::iterator {aka std::_Rb_tree_const_iterator<std::__cxx11::basic_string<char> >}
”的转换multiset.cpp:47:1:注意:候选人:
my_multiset::iterator::iterator() my_multiset::iterator::iterator(void){}
multiset.h:17:10:注意:参数1没有已知的从“
的已知转换std::_Rb_tree_const_iterator<std::__cxx11::basic_string<char> >*
”到“const cpt323::my_multiset::iterator&
”的转换 multiset.h:17:10:注意:候选人:constexpr my_multiset::iterator::iterator(cpt323::my_multiset::iterator&&)
multiset.h:17:10:注意:参数1没有从'std::_Rb_tree_const_iterator<std::__cxx11::basic_string<char> >*
'到'my_multiset::iterator&&
'
除了本部分(有关如何进行适当更改的任何建议)外,该代码均在正常工作
class my_multiset : custom_datastructure
{
std::multiset<std::string> the_set;
std::multiset<std::string>::iterator head;
std::multiset<std::string>::iterator tail;
public:
class iterator : public custom_datastructure::iterator
{
std::multiset<std::string>::iterator current;
public:
iterator(void){};
iterator(std::multiset<std::string>::iterator a_set) : current(a_set)
{
}
};
multiset(void);
std::unique_ptr<custom_datastructure::iterator> begin(void)
{
head = the_set.begin();
return std::make_unique<my_multiset::iterator>(&head);
}
std::unique_ptr<custom_datastructure::iterator> end(void)
{
tail = the_set.end();
return std::make_unique<my_multiset::iterator>(&tail);
}
}
custom_data结构如下
struct datastructure
{
struct iterator
{
/** OPERATORS HERE **/
virtual std::unique_ptr<datastructure::iterator> operator++(void) = 0;
/** ETC **/
};
virtual std::unique_ptr<iterator> begin(void) = 0;
virtual std::unique_ptr<iterator> end(void) = 0;
}
答案 0 :(得分:0)
代码中断的原因是因为unique_ptr
不能用作迭代器,所以当从unique_ptr
和{{1返回时,将迭代器包装在begin()
中}},那么它就不再可用作迭代器。
迭代器不必是指针;它只需要像一个人一样。另外,迭代器不应该拥有数据。如果类负责删除数据,则该类拥有数据,但是迭代器不负责删除任何数据。它仅应提供一种访问数据的方式。这意味着迭代器可以并且应该按值传递(而不是使用end()
)。
所以这是一个大问题:您是要创建一个返回一些迭代器的接口,还是要为一个像迭代器一样的东西创建一个接口?
最通用的方法是通过模板。使用模板的好处在于,它使我们能够在各种情况下重用此接口,并且我们可以std::unique_ptr
在需要的接口上使用它,而在定义模板的文件中没有任何依赖关系。
#include
我们可以使用它来将template<class Iterator>
class Iterable {
public:
virtual Iterator begin() = 0;
virtual Iterator end() = 0;
};
定义为将迭代器返回到my_multiset
:
std::multiset
class my_multiset
: public Iterable<typename std::multiset<std::string>::iterator>
{
std::multiset<std::string> the_set;
public:
using iterator = typename std::multiset<std::string>::iterator;
iterator begin() override {
return the_set.begin();
}
iterator end() override {
return the_set.end();
}
};
-可以分配任何迭代器的类因为指向迭代器的指针的行为类似于指针,而不是底层的迭代器,因此我们将不希望使用GenericIterator<Value>
,而是要创建一个包装类来为我们处理所有事务,同时仍然像一个普通的迭代器。
您将能够像使用任何旧的迭代器一样使用它,除了可以使用迭代器将其分配或创建给取消引用unique_ptr<BaseIterator>
的任何对象。这意味着同一个GenericIterator可以绑定到列表迭代器,向量迭代器甚至是Value
迭代器。
显示如何使用它的示例:
std::multiset
我们需要制造#include <iostream>
#include <list>
#include <vector>
int main()
{
std::vector<int> v{1, 2, 3};
std::list<int> l{10, 20, 30};
GenericIterator<int&> begin, end;
begin = v.begin();
end = v.end();
for (; begin != end; ++begin)
{
std::cout << *begin << " ";
}
begin = l.begin();
end = l.end();
for (; begin != end; ++begin)
{
std::cout << *begin << " ";
}
}
的哪些零件?
GenericIterator
将存储指向虚拟基类的指针。我们还需要一个派生类,该派生类为特定的Iter实现基础。
基类:
基类虚拟化迭代器的主要功能:增量,取消引用和相等。它还提供了一个GenericIterator
方法,以便可以复制迭代器。在编写包含此功能的clone()
类时,close()
会派上用场。
GenericIterator
派生类:
该派生类基本上可以包装地球上的任何其他迭代器,并且它重写template <class Value>
class IteratorBase
{
public:
virtual Value operator*() const = 0;
virtual IteratorBase& operator++() = 0;
virtual bool operator!=(IteratorBase const&) const = 0;
virtual bool operator==(IteratorBase const&) const = 0;
// We need this function for making copies of the iterator
virtual IteratorBase* clone() const = 0;
virtual ~IteratorBase() = default;
};
中的所有方法以提供功能全面的迭代器。
IteratorBase
通用包装:
template <class Iter, class Value>
class IteratorDerived : public IteratorBase<Value>
{
Iter it;
public:
IteratorDerived() = default;
IteratorDerived(Iter it) : it(it) {}
IteratorDerived(IteratorDerived const&) = default;
IteratorDerived(IteratorDerived&&) = default;
Value operator*() const override { return *it; }
IteratorBase<Value>& operator++() override
{
++it;
return *this;
}
bool operator!=(IteratorBase<Value> const& other) const override
{
auto* derived = dynamic_cast<IteratorDerived const*>(&other);
return derived == nullptr || it != derived->it;
}
bool operator==(IteratorBase<Value> const& other) const override
{
auto* derived = dynamic_cast<IteratorDerived const*>(&other);
return derived != nullptr && it == derived->it;
}
IteratorBase<Value>* clone() const override
{
return new IteratorDerived(*this);
}
};
封装了迭代器的所有功能,并且由于我们的编写方式,您可以自动将所有引用迭代器的迭代器分配给匹配的值类型。
GenericWrapper
可选:C ++ 17模板推论指南
我们可以为template <class Value>
class GenericIterator
{
std::unique_ptr<IteratorBase<Value>> iterator;
public:
GenericIterator() = default;
GenericIterator(GenericIterator const& it) : iterator(it.iterator->clone())
{
}
GenericIterator(GenericIterator&&) = default;
// Creates a GenericIterator from an IteratorBase
explicit GenericIterator(IteratorBase<Value> const& it)
: iterator(it.clone())
{
}
// Creates a GenericIterator from an IteratorDerived
template <class Iter>
explicit GenericIterator(IteratorDerived<Iter, Value> const& it)
: iterator(it.clone())
{
}
// Creates a GenericIterator by wrapping another Iter
template <class Iter>
GenericIterator(Iter it) : iterator(new IteratorDerived<Iter, Value>(it))
{
}
GenericIterator& operator=(GenericIterator const& it)
{
iterator = std::unique_ptr<IteratorBase<Value>>(it.iterator->clone());
return *this;
}
GenericIterator& operator=(GenericIterator&&) = default;
Value operator*() const { return *(*iterator); }
GenericIterator& operator++()
{
++(*iterator);
return *this;
}
bool operator==(GenericIterator const& other) const
{
return *iterator == *other.iterator;
}
bool operator!=(GenericIterator const& other) const
{
return *iterator != *other.iterator;
}
};
编写模板类型推导指南,该指南会自动填写正确的模板参数,从而很容易包装其他迭代器。
GenericIterator