Nat*_*rez 0 c++ containers stl typeid
我正在编写一个小模板类,它可以作为模板参数列表或向量(显然还有数据类型)。我需要重载 [ ] 运算符,为此我想使用向量的重载 [ ] 并对列表进行简单的搜索(下一个,下一个,直到我们到达所需的索引)。所以我正在检查 typeid 是否参数是列表的参数并根据这样的结果实现:
const T* operator[](size_t _index)const
{
if(typeid(ContainerT<T,std::allocator<T> >) == typeid(vector<T>))
{
return m_container[_index];
}
else
{
const_iterator it = m_container.begin();
for(int i=0;i<_index;++i)
{
++it;
}
return *it;
}
}
Run Code Online (Sandbox Code Playgroud)
如果我不将 [ ] 用于列表,则一切正常,但是当我使用它时:
tContainer_t<int, list> list1;
cout<<list1[0]<<endl;
Run Code Online (Sandbox Code Playgroud)
它根本没有编译,这是编译错误:
In file included from main.cpp:6:0:
tContainer.h: In member function ‘const T* tContainer_t<T, ContainerT>::operator[](size_t) const [with T = int, ContainerT = std::list, size_t = unsigned int]’:
main.cpp:68:9: instantiated from here
tContainer.h:80:29: error: no match for ‘operator[]’ in ‘((const tContainer_t<int, std::list>*)this)->tContainer_t<int, std::list>::m_container[_index]’
Run Code Online (Sandbox Code Playgroud)
我不明白,因为我检查了 typeid 确实有效(我认为......),无论如何似乎编译器看到下标也将被调用以获取列表。
由于编译器需要编译整个函数,即使在运行时不会采取一个分支(由于检查),那么您不能使用这种类型的运行时检查来防止编译错误。
有一些方法可以做到这一点,包括使用可以专门用于该类型的辅助函数。但是,它可能很复杂,在这种情况下,不值得自己做,因为标准库已经为您完成了工作。
std::advance(位于 header 中<iterator>)可用于将迭代器推进 N 次,并针对随机访问迭代器(如std::vector或返回的迭代器)进行优化以std::deque在恒定时间内完成。否则它会使用++
// Note, changed signature to return const T&, which is more standard for operator[]
const T& operator[](size_t index) const
{
const_iterator itr = m_container.begin();
std::advance(itr, index);
return *itr;
}
Run Code Online (Sandbox Code Playgroud)
编辑:
假设您想了解它是如何完成的,您将创建以下函数,通常在一个单独的命名空间中。现在,我将使用问题的原始意图,并假设您正在使用std::list或std::vector。
namespace helper
{
template <typename T, typename Alloc>
typename std::vector<T,Alloc>::const_reference
index_into(std::vector<T, Alloc> const& container, std::size_t index)
{
return container[index];
}
template <typename T, typename Alloc>
typename std::list<T,Alloc>::const_reference
index_into(std::list<T, Alloc> const& container, std::size_t index)
{
std::list<T, Alloc>::const_iterator itr = container.begin();
for(std::size_t i = 0; i < index; ++i)
{
++itr;
}
return *itr;
}
}
// Change your definition here
const T& operator[](size_t index) const
{
return helper::index_into(m_container, index);
}
Run Code Online (Sandbox Code Playgroud)
为什么这样做:当您使用 std::list 或 std::vector 编译它时,它使用函数重载来确定index_into要使用的两个重载中的哪一个。因此,它只编译合法的一个,而不尝试编译两者。
请注意,实现只允许 std::vector 和 std::list。如果您想允许任何容器, usingstd::advance是通用且正确的解决方案。
仅供参考,实现std::advaance使用类似的技术。您可以查看您的实现以了解它是如何完成的。
| 归档时间: |
|
| 查看次数: |
1059 次 |
| 最近记录: |