C ++ 0x: шаблон слайса не может быть скомпилирован с использованием диапазона () - PullRequest
0 голосов
/ 15 октября 2011

Я получаю следующую ошибку компиляции в gcc 4.6.1 при попытке получить класс шаблона Slice для работы с range-based for () (встречается в строке for () с auto):

  1. Я знаю, что в надстройке есть класс срезов - это только для иллюстрации
  2. Мне удалось добиться того, чтобы for () работал на основе ранжирования, чтобы нормально работать с простым классом - просто возникли проблемы с классом шаблона.

Что я делаю не так?

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 Ответ

3 голосов
/ 15 октября 2011

Параметры шаблона begin и end установлены неправильно.Они передаются 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::begin будетнайден путем поиска, зависящего от аргумента, даже если ваш тип не является частью пространства имен std.Меньше работы с вашей стороны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...