没有已知的转化

时间:2019-05-13 20:05:06

标签: c++

我的构造函数有问题。

我收到以下错误:

  

未知参数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;
}

1 个答案:

答案 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