c ++:模板容器,operator []无法按预期工作

时间:2016-03-06 21:40:11

标签: c++

我正在尝试实现一个包装的模板类 指针的STL容器,如:

tContainer_t<T, vector<T*> >

tContainer_t<T, list<T*> >

这是类声明:

template <typename T, typename Container>
class tContainer_t
{
public:
    tContainer_t() {} //Default CTOR
    ~tContainer_t() {} //DTOR
    bool IsEmpty() const;
    size_t Size() const;
    bool Insert(T* _element);
    T* Find(T _value);
    T* Remove(T _value);
    T* operator[](size_t _index);
private:
    tContainer_t(const tContainer_t& _other); //Disable Copy
    Container m_container;
};

我想练习operator []的不同实现(对于vector和list),所以我写道:

template <typename T, typename Container>
T* tContainer_t<T, Container>::operator[](size_t _index)
{
    T* retval;
    if (_index > m_container.size())
    {
        return 0;
    }
    if (typeid(m_container) == typeid(vector<T*>))
    {
        retval = m_container[_index];
    }
    if (typeid(m_container) == typeid(list<T*>))
    {
        typename Container::iterator contIter = m_container.begin();
        advance(contIter, _index);
        retval = *contIter;
    }
    return retval;
}

我的行为很奇怪。当我在main中使用向量时,代码工作正常。当我使用列表时,它甚至不编译,显示:

container.h: In instantiation of ‘T* tContainer_t<T, Container>::operator[](size_t) [with T = int; Container = std::list<int*>; size_t = long unsigned int]’:
container.cpp:10:14:   required from here
container.h:141:23: error: no match for ‘operator[]’ (operand types are ‘std::list<int*>’ and ‘size_t {aka long unsigned int}’)
   retval = m_container[_index];

以下是我使用它的方式:

int main(int argc, char const *argv[])
{
    tContainer_t<int, list<int*> > a;
    int i = 5;
    a.Insert(&i);
    cout << *a[0] << endl;
    return 0;
}

1 个答案:

答案 0 :(得分:2)

所有函数中的代码都将被编译,无论它是否会被运行。所以这个:

if (typeid(m_container) == typeid(vector<T*>))
{
    retval = m_container[_index];
}

不可能适用于list<T>,因为list没有operator[]。因此编译错误。它不会运行并不重要,它仍然需要编译。相反,这样做的方法是根据m_container

的类型调度到不同的函数
template <typename T, typename Container>
T* tContainer_t<T, Container>::operator[](size_t _index)
{
    if (_index > m_container.size())
    {
        return 0;
    }

    return _get_index(m_container, _index);
}

使用vector版本:

template <class T>
T* tContainer_t<T, Container>::_get_index(std::vector<T*>& v, size_t _index) {
    return v[_index];
}

list版本:

template <class T>
T* tContainer_t<T, Container>::_get_index(std::list<T*>& lst, size_t _index) 
{
    typename Container::iterator contIter = lst.begin();
    advance(contIter, _index);
    return *contIter;
}

至少这是一个很好的通用方法。在这种情况下,我们实际上不必拆分它们,因为我们可以对两种容器类型使用advance()。对于vector来说它会很便宜而对list来说很贵......

template <typename T, typename Container>
T* tContainer_t<T, Container>::operator[](size_t _index)
{
    if (_index >= m_container.size())  // note the off-by-one error I fixed here
    {
        return nullptr;
    }

    auto it = m_container.begin();
    std::advance(it, _index);
    return *it;
}

或者简单地说:

return *std::next(m_container.begin(), _index);