2012-10-03 58 views
0

基本上,我试图写有一个通用的迭代的基类。C++虚拟的boost ::任何继承

因此很明显,模板虚拟功能不起作用,这就是为什么我想的boost ::任何,但它仍然不会重载Iterator的get()方法(它继续抛出下面定义的Exception)。我似乎也无法使其成为纯虚拟的,因为编译器抱怨'虚拟迭代器begin()= 0;' (它表示'不能创建抽象类Iterator的实例')。

我有非常具体的限制,我必须/要坚持,所以可能会考虑替代解决方案的问题,但可能无法使用。

下面是代码的一部分:

template <class T, class C> 
    class Iterator 
    { 
    public: 
     virtual T& operator*() { T *t = boost::any_cast<T>(&get()); return *t; }; 
     virtual boost::any& get() { throw new Exception("get not overridden!!"); }; 
     //virtual boost::any& get() = 0; 
    protected: 
     C::iterator iter; 
    }; 

    template <class T> 
    class VectorIterator: public Iterator<T, std::vector<T> > 
    { 
    public: 
     VectorIterator(std::vector<T>::iterator iterator): Iterator<T, std::vector<T> >(iterator) { }; 
     virtual boost::any& get() { return *iter; }; 
    }; 

    template <class Value, class Container> 
    class Repository 
    { 
    public: 
     typedef Iterator<Value, Container> iterator; 

     virtual iterator begin() = 0; 
     virtual iterator end() = 0; 
    }; 


    class SomeRepository : public Repository<RandomClass, std::vector<RandomClass> > 
    { 
    public: 
     iterator begin() { return VectorIterator<RandomClass>(items.begin()); }; 

     iterator end() { return VectorIterator<RandomClass>(items.end()); }; 
    } 

那么,为什么没有工作,(如何)可以解决呢? PS:我知道这与另一个问题非常相似,但我无法准确地将其纳入评论中,而且我不知道我还能够把它放在哪里。

UPDATE:

所以我设法让GET推测出来的东西()返回一个void(EWW)指针和忘掉的boost ::任何。但它仍然调用Iterator :: get而不是VectorIterator :: get(正如我原来的问题)(当我尝试使用* someRepository.begin())时,有人知道为什么吗?

+0

我很好奇。这应该达到什么目的?如果你想在迭代器上输入erase,那么有更好的方法可用。 – pmr

+7

'抛出新的异常(...);' - 请不要... – Xeo

+0

@pmr我们的代码中存在迭代通过Repository的所有元素的现有功能,我认为更好的方法是创建一个这个泛型迭代器。 – Dukeling

回答

0

如果你在'iterator begin()'中返回Iterator(所以按值返回),它会将返回值转换为Iterator,因此它不再是VectorIterator类型,显然它不会调用VectorIterator的get方法至少这是我的想法)。通过引用或指针返回应该工作得很好。

现在我只需要弄清楚一个解决方法。由于我在VectorIterator :: begin()中返回一个局部变量,因此通过引用返回将无法工作。我想我必须通过指针返回,除非别人有更好的建议。

+0

通过boost :: shared_ptr返回可能是一个更好的主意。 – Dukeling

3

您无法从*iter初始化boost::any&,就像您无法从int类型的值初始化float&一样。在这两种情况下都没有所需类型的实际对象可以参考。

您可以更改get返回boost::any(在这种情况下,从*iter转换会发生),但随后你的operator*有它要参考(再次,引用类型)的T的问题需要活得比功能呼叫。一种解决方案是在某处存储调用get的结果,或者通过使operator*返回值(T)而不是参考文件(T&)来执行与get相同的更改。这些将是价值语义,而不是对底层容器的“浅”视图。分配operator*的结果,假设它是正确的,不会影响容器的元素。

另一种可能性是使get返回boost::any,该boost::any保证在元素中存储浅视图,例如,

virtual boost::any get() { return &*iter; } 

return boost::ref(*iter);是另一种可能性)

必须多加然后采取内部operator*正确恢复的预期值,例如return *boost::any_cast<T*>(get());(或return boot::any_cast<boost::reference_wrapper<T> >(get()).get();)。这有引用语义,其中返回T&会很好。对operator*结果的操作可能会影响容器的元素。