Как предоставить бесплатные начальные / конечные функции для ваших собственных типов - PullRequest
9 голосов
/ 28 сентября 2011

В одном из своих последних выступлений Херб Саттер рекомендовал использовать бесплатные begin(container) end(container) шаблоны функций вместо container.begin(). Мне это нравится, потому что эти функции могут быть предоставлены для всех итерируемых типов, которые не поставляются с методами begin () / end (). Поскольку большинство моих классов доменов имеют интерфейсы, которые говорят на языке домена и не используют общие имена, такие как begin / end, теперь я могу предоставить итеративный интерфейс, совместимый с контейнерами STL и основой диапазона для циклов, не путая интерфейс основного класса. Мне интересно, как лучше всего обеспечить начало / конец функций для моих собственных типов. Моей первой мыслью было сделать то же самое, что я сделал с swap и написать функцию в том же пространстве имен, где живет мой тип.

namespace My
{

class Book
{
public:
    typedef std::vector<Page>::const_iterator PageIterator;

    PageIterator FirstPage() const { return begin(pages_); }
    PageIterator LastPage() const { return end(pages_); }

private:
    std::vector<Page> pages_;
};

Book::PageIterator begin(const Book& b)
{
    return b.FirstPage();
}

Book::PageIterator end(const Book& b)
{
    return b.LastPage();
}

}

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

Ответы [ 2 ]

9 голосов
/ 28 сентября 2011

Я бы позволил ADL сделать свою работу. Хотя вам разрешено добавлять специализации в пространство имен std, я не думаю, что для этого есть веские причины, когда достаточно простой функции в вашем пространстве имен.

В частности, для диапазона для петель стандартные состояния:

§6.5.4 / 1 (определение begin-expr и end-expr ):

  • в противном случае begin-expr и end-expr равны begin(__range) и end(__range) соответственно, где начало и конец ищутся с помощью аргумент-зависимого поиска (3.4.2). Для целей поиска этого имени пространство имен std является связанным пространством имен.
5 голосов
/ 28 сентября 2011

Это нормально и рекомендуется "положиться" на ADL.Функции begin и end являются частью интерфейса вашего типа (независимо от того, являются ли они автономными функциями или нет), и они должны находиться в том же пространстве имен, что и ваш тип.

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