c++ - 容器 STL 的 typeid

标签 c++ stl containers typeid

我正在编写一个小模板类,它可以作为模板参数列表或 vector (显然还有数据类型)获取。 我需要重载 [ ] 运算符,为此我想使用 vector 的重载 [ ] 并对列表进行简单搜索(下一步,下一步,直到我们到达所需的索引)。 所以我正在检查 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;
    }
}

如果我不使用 [ ] 作为列表,一切正常,但是当我使用它时:

tContainer_t<int, list> list1;
cout<<list1[0]<<endl;

它根本没有编译,这是编译错误:

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]’

我不明白,因为我检查了 typeid 确实有效(我认为......)而且无论如何编译器似乎看到下标也将被调用列表。

最佳答案

由于编译器需要编译整个函数,即使在运行时不会采取一个分支(由于检查),那么您不能使用这种运行时检查来防止编译错误。

有一些方法可以做到这一点,包括使用可以专用于该类型的辅助函数。然而,它可能很复杂,在这种情况下,不值得您自己动手,因为标准库已经为您完成了这项工作。

std::advance (位于标题 <iterator> 中)可用于将迭代器推进最多 N 次,并针对随机访问迭代器(如 std::vectorstd::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;
}

编辑:

假设您想了解它是如何完成的,您将创建以下函数,通常在单独的命名空间中。现在,我将使用问题的初衷,并假设您使用的是 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);
}

为什么会这样:当你用 std::list 或 std::vector 编译它时,它使用函数重载来确定 index_into 的两个重载中的哪一个。使用。因此,它只编译合法的,不会同时编译两者。

请注意,实现仅允许 std::vector 和 std::list。如果你想允许任何容器,使用 std::advance是通用且正确的解决方案。

仅供引用,std::advaance 的实现使用类似的技术。您可以查看您的实现以了解它是如何完成的。

关于c++ - 容器 STL 的 typeid,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11729218/

相关文章:

c++ - Visual C++ - 生成问题

C++ Socket recv 未接收到正确的字节数?

C++ STL vector 迭代器...但出现运行时错误

java - 在容器而不是 web.xml 中指定身份验证

docker - 如何在Docker容器和主机之间共享数据?

c++ - 如何初始化构造函数初始化列表中 `std::vector` 对象的类成员 `std::unique_ptr`?

c++ - OpenGL:关于使用多个纹理或纹理单元的一些说明

c++ - 通过 B 类,我想在 main 中打印 A 类函数

C++ 映射行为不正常

c++ - C++ STL map 如何管理内存,以及如何绕过它