【问题标题】:Custom STL container wrapper report weird compiler error自定义 STL 容器包装器报告奇怪的编译器错误
【发布时间】:2011-02-12 00:15:34
【问题描述】:

我有一个 C++ 库(包含 50 多个源文件),它使用大量 STL 例程,主容器为 listvector。这导致了巨大的代码膨胀,我想通过创建另一个本质上是包装器的库来减少代码膨胀 在listvector 上。

我基本上需要一个围绕std::list 的包装器,它适用于任何类型的列表容器。

下面显示的是我的列表包装类。

template<typename T>
class wlist
{
private:
    std::list<T> m_list;

public:

    wlist();

    typedef std::list<void*>::iterator Iterator;
    typedef std::list<void*>::const_iterator CIterator;

    unsigned int size () { return m_list.size(); }
    bool empty () { return m_list.empty(); }
    void pop_back () { m_list.pop_back(); }
    void pop_front () { m_list.pop_front(); }
    void push_front (const T& item) { m_list.push_front(item); }
    void push_back (const T& item) { m_list.push_back(item); }
    bool delete_item (void* item);
    T& back () { return (m_list.empty()) ? NULL : m_list.back();}
    T& front () { return (m_list.empty()) ? NULL : m_list.front();}
    Iterator erase() { return m_list.erase(); }
    Iterator begin() { return (Iterator) m_list.begin(); }
    Iterator end() { return (Iterator) m_list.end(); }
};

文件1.h:

class label{

public:
int getPosition(void);
setPosition(int x);

private:
wlist<text> _elementText; // used in place of list<text> _elementText;

}

文件2.h:

class image {

private:

    void draw image() {
        //Used instead of list<label*>::iterator currentElement = _elementText.begin();
        wlist<label*>::iterator currentElement = _elementText.begin();
        currentElement->getPosition(); // Here is the problem.     
        currentElement ++;
    }
}

使用以下错误消息调用 getPosition() 炸弹:

error: request for member `getPosition' in `*(&currentElement)->std::_List_iterator<_Tp>::operator-> [with _Tp = void*]()', which is of non-class type `void*'

类型转换 getPosition()label 类型不起作用。此外,我的迭代器类型为 void*

【问题讨论】:

    标签: c++ stl iterator wrapper


    【解决方案1】:

    我认为问题在于这条线

    currentElement->getPosition();
    

    不会工作,因为currentElementvoid*s 上的迭代器,而不是labels。由于某些类型T 上的迭代器的行为类似于T*s,这意味着您的currentElement 迭代器的行为类似于label**,因此编写上述代码类似于编写

    (*currentElement).getPosition();
    

    在这里,问题应该更容易看出 - *currentElementlabel*,而不是 label,因此您不能在其上使用点运算符。

    要解决此问题,请尝试将此代码更改为

    ((label *)(*currentElement))->getPosition();
    

    这会取消对迭代器的引用并对void* 进行类型转换以获取label*,然后使用箭头运算符在被指向的label 上调用getPosition() 函数。

    【讨论】:

    • 我应该如何在 wlist 中声明 erase()、begin() 和 end()。我当前的声明引发了如下错误:错误:无法将 ((std::list&lt;label*, std::allocator&lt;label*&gt; &gt;*)this)-&gt;std::list&lt;_Tp, _Alloc&gt;::end [with _Tp = label*, _Alloc = std::allocator&lt;label*&gt;]()' from type std::_List_iterator 类型
    • 我认为您的几乎所有问题都源于您的迭代器正在迭代void*s,这确实不是正确的方法。我认为您确实希望您的迭代器具有T 类型,并且问题很可能是如果您尝试将它们定义为typedef std::list&lt;T&gt;::iterator iterator 您会收到编译器错误。正确的做法是将其写为typedef typename std::list&lt;T&gt;::iterator iterator,因为std::list&lt;T&gt;::iterator 是一个依赖类型。尝试这样做,看看它是否可以简化事情。
    【解决方案2】:

    您的迭代器类型似乎是用std::list&lt;void*&gt;::iterator 声明的。这对我来说听起来不对...

    【讨论】:

    • typedef std::list::iterator 迭代器;这引发了编译错误
    • 错误:输入std::list&lt;T, std::allocator&lt;_CharT&gt; &gt;' is not derived from type wstl::wlist' 并且派生不是一个选项
    • @codebin:应该是typedef typename std::list&lt;T&gt;::iterator Iterator;(为了更通用,您的迭代器也可以以小写的 i 开头)。 - 至于你的void* typedef,我的编译器说list&lt;T&gt;::iterator 不能转换为list&lt;void*&gt;::iterator
    猜你喜欢
    • 2016-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多