C ++ 0x:切片模板无法编译,基于范围为()

时间:2011-10-15 06:39:07

标签: c++ templates c++11

我试图让Slice模板类使用基于范围的for()(在带有auto的for()行上时,在gcc 4.6.1中得到以下编译错误:

  1. 我知道在提升中有一个切片类 - 这仅用于说明目的
  2. 我设法让基于范围的for()在普通类中正常工作 - 只是遇到模板类问题。
  3. 我做错了什么?

      

    sandbox.cpp:31:17:错误:无法将‘(& t)->Slice<T>::Begin [with T = int, typename std::vector<_RealType>::const_iterator = __gnu_cxx::__normal_iterator<const int*, std::vector<int> >]()’‘const const_iterator {aka const __gnu_cxx::__normal_iterator<const int*, std::vector<int> >}’转换为‘std::vector<Slice<int>, std::allocator<Slice<int> > >::const_iterator {aka __gnu_cxx::__normal_iterator<const Slice<int>*, std::vector<Slice<int>, std::allocator<Slice<int> > > >}’

         

    sandbox.cpp:在函数‘typename std::vector<_RealType>::const_iterator end(const T&) [with T = Slice<int>, typename std::vector<_RealType>::const_iterator = __gnu_cxx::__normal_iterator<const Slice<int>*, std::vector<Slice<int>, std::allocator<Slice<int> > > >]’

    代码:

    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    template< typename T >
    class Slice 
    {
    public:
        Slice( const vector< T >& v,
            typename vector< T >::const_iterator it0, 
            typename vector< T >::const_iterator itEnd ) :
            m_v( v ), m_it0( it0 ), m_itEnd( itEnd )
        { }
    
    public:
        const typename vector<T>::const_iterator Begin() const
            { return m_it0;     }
        const typename vector<T>::const_iterator End()   const
            { return m_itEnd; }
    
    private:
        const vector< T >&                         m_v;
        const typename vector< T >::const_iterator m_it0, m_itEnd;
    };
    
    template< typename T >
    typename vector<T>::const_iterator
    begin( const T& t )
    {
        return t.Begin();
    }
    
    template< typename T >
    typename vector<T>::const_iterator
    end( const T& t )
    {
        return t.End();
    }
    
    int main(int argc, char** argv)
    {
        vector<int> v = { 1, 2, 3, 4, 5, 6 };
        Slice<int>  s( v, v.begin()++, v.end() );
        for( auto x : s ) 
        {
    
        }
        return 0;
    }
    

1 个答案:

答案 0 :(得分:3)

您的beginend模板参数设置错误。它们被s传递,Slice<int>,因此T被推断为Slice<int>。那么返回类型是vector<Slice<int> >::const_iterator。但Slice<int>::Begin会返回vector<int>::const_iterator

正如您在评论中提到的,解决方案是将参数从const T&更改为const Slice<T>&。这样,T推断为int而不是Slice<int>,返回类型变为vector<int>::const_iterator,如您所愿。

template<typename T>
typename std::vector<T>::const_iterator
begin(const Slice<T>& s) {
  return s.Begin();
}

但是,如果您将功能的名称更改为begin而不是Begin,则可以使用std::begin,它具有更通用的行为:

template<typename T>
auto begin(const T& t) 
-> decltype(t.begin()) {
  return t.begin();
}

基于范围的for语句有一个特殊规则,即使您的类型不是命名空间std的一部分,也可以通过参数依赖查找找到std::begin。你的工作量较少。