首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >容器STL的typeid

容器STL的typeid
EN

Stack Overflow用户
提问于 2012-07-31 04:38:59
回答 2查看 1.1K关注 0票数 0

我正在写一个小的模板类,它可以作为模板参数列表或向量(当然还有数据类型)。我需要重载运算符,为此,我想使用向量的重载,并对列表进行简单的搜索(下一步,下一步,直到我们找到所需的索引)。所以我使用typeid检查参数是否为list的参数,并根据如下结果实现:

代码语言:javascript
复制
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;
    }
}

如果我不使用列表,一切都可以,但我使用它时:

代码语言:javascript
复制
tContainer_t<int, list> list1;
cout<<list1[0]<<endl;

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

代码语言:javascript
复制
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是否正常工作(嗯,我想...)不管怎么说,编译器似乎看到了列表的下标也会被调用。

EN

回答 2

Stack Overflow用户

发布于 2012-07-31 04:49:58

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

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

std::advance (位于header <iterator>中)可用于使迭代器前进N次,并针对随机访问迭代器(如std::vectorstd::deque返回的迭代器)进行了优化,以在固定时间内完成此任务。否则,它将退回到使用++一次执行一个步骤

代码语言:javascript
复制
// 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::liststd::vector

代码语言:javascript
复制
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的实现使用了类似的技术。您可以查看您的实现,以了解它是如何完成的。

票数 5
EN

Stack Overflow用户

发布于 2012-07-31 04:49:22

使用<iterator>中的std::advance

代码语言:javascript
复制
const T* operator[](size_t index) const
{
    const_iterator it = m_container.begin();
    std::advance(it, index);
    return &*it;
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11729218

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档