Шаблон C ++ с параметром по умолчанию - PullRequest
0 голосов
/ 15 февраля 2012

Я впервые пытаюсь реализовать собственный контейнер, совместимый с STL, с его итератором, но у меня возникают некоторые проблемы с синтаксисом и использованием шаблонов. Это часть моего заголовочного файла:

namespace unstd {

template<typename T,class Allocator = std::allocator<T>>
class SList
{

public:

    typedef typename Allocator::value_type value_type;
    typedef typename size_t size_type;
    typedef typename Allocator::template rebind<T>::other allocator_type;
    typedef typename Allocator::reference reference;
    typedef typename Allocator::const_reference const_reference;
    typedef typename T* pointer;
    typedef typename const T* const_pointer;
    typedef typename ptrdiff_t difference_type;

    typedef typename SList_Iterator_Forward<T> iterator;
    typedef typename const SList_Iterator_Forward<T> const_iterator;

....
        /*----- ITERATORS -------*/
    iterator begin();
    ...
    };}

Давайте рассмотрим, например, метод begin (). Я написал следующее (в файле .cpp), который не компилируется:

template<typename T, class Allocator>
iterator SList<T,Allocator>::begin()
{

}
//neither the following compile
template<typename T, class Allocator>
SList<T,Allocator>::iterator SList<T,Allocator>::begin()
{

}

У меня есть несколько вопросов:

  1. Почему это не компилируется? (ошибка C2143 синтаксическая ошибка: отсутствует 'token1' перед 'token2')
  2. Почему я должен явно назначать все параметры шаблона, даже параметры по умолчанию? (Почему я не могу указать только T, учитывая, что у Allocator есть значение по умолчанию?)
  3. Правильно ли отделять заголовок от реализации в этой ситуации?

Ответы [ 2 ]

2 голосов
/ 15 февраля 2012

1)

template<typename T, class Allocator>
typename SList<T,Allocator>::iterator SList<T,Allocator>::begin()
^^^^^^^^

Это раздражает, но привыкни.Компилятор предполагает, что все подобные шаблонные вещи являются переменными, поэтому, если это тип, вы должны сказать это конкретно.

2) Компилятор должен знать, что определение функции предназначено для класса SList, который имеет два параметра шаблона, и что оба могут быть чем угодно, это не специализация.Я понимаю, что ваш по умолчанию и не будет двусмысленным, если бы по умолчанию не было, но я думаю, что это в первую очередь упрощает компиляторы.

3) Определения могут быть в отдельном файле, ноне в своем собственном «модуле перевода» (скомпилированный файл .cpp и он включает в себя).Так что не помещайте это в .cpp, это просто сбивает с толку.Нередко определения шаблонов находятся в файле .incl, который находится внизу заголовка.Это делает компилятор счастливым, и у вас все еще есть разделение объявления и определения.

1 голос
/ 15 февраля 2012
  1. По нескольким причинам:

    • Вам не хватает SList<T,Allocator>:: перед типом возврата iterator из begin

    • iterator является зависимым типом, поэтому вам нужно typename перед SList<T, Allocator>::iterator в обоих местах

    • Вы не возвращаете значение изфункция с типом возвращаемого значения, отличным от void;вам нужно что-то вернуть.

  2. Поскольку имя SList<T, Allocator>, и вы должны сообщить компилятору полное имя класса, потому что вам нужно уметьссылаться на имя типа Allocator, и потому что это именно так.

  3. Вы не можете, потому что компилятор требует, чтобы реализация шаблонов находилась в том же файле, что иобъявление (если вы не сделаете явное создание экземпляров, которые ограничивают универсальность шаблонов).Таким образом, вам нужно будет #include реализации в файл интерфейса в конце.

...