我正在尝试实现一个包装的模板类 指针的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;
}
答案 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);